View on GitHub
ejpp
Embedded JSON Database engine for C++11/14
ejdb.hpp
1 /******************************************************************************
2  *
3  * C++11 wrapper for EJDB (http://ejdb.org)
4  * Copyright (C) 2013 Christian Manning
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19  * USA
20  *****************************************************************************/
21 
22 #ifndef EJDB_HPP
23 #define EJDB_HPP
24 
25 #include <memory>
26 #include <string>
27 #include <system_error>
28 #include <vector>
29 #include <array>
30 #include <experimental/optional>
31 
32 #include <boost/config.hpp>
33 
34 struct EJDB;
35 struct EJCOLL;
36 struct EJQ;
37 
38 #ifndef EJPP_EXPORTS
39 #define EJPP_EXPORT BOOST_SYMBOL_IMPORT
40 #else
41 #define EJPP_EXPORT BOOST_SYMBOL_EXPORT
42 #endif
43 
44 #ifndef EJPP_LOCAL
45 #if defined(__GNUC__)
46 #define EJPP_LOCAL __attribute__((__visibility__("hidden")))
47 #else
48 #define EJPP_LOCAL
49 #endif
50 #endif
51 
56 namespace ejdb {
57 struct collection;
58 struct query;
59 
61 enum class db_mode {
62  read = 1 << 0,
63  write = 1 << 1,
64  create = 1 << 2,
65  truncate = 1 << 3,
66  nolock = 1 << 4,
67  noblock = 1 << 5,
68  trans_sync = 1 << 6
69 };
70 
72 constexpr inline db_mode operator|(db_mode lhs, db_mode rhs) noexcept {
73  return (db_mode)((std::underlying_type<db_mode>::type)lhs | (std::underlying_type<db_mode>::type)rhs);
74 }
75 
77 constexpr inline db_mode& operator|=(db_mode& lhs, db_mode rhs) noexcept { return lhs = lhs | rhs; }
78 
80 enum class index_mode {
81  drop = 1 << 0,
82  drop_all = 1 << 1,
83  optimize = 1 << 2,
84  rebuild = 1 << 3,
85  number = 1 << 4,
86  string = 1 << 5,
87  array = 1 << 6,
88  istring = 1 << 7
89 };
90 
92 constexpr inline index_mode operator|(index_mode lhs, index_mode rhs) noexcept {
93  return (index_mode)((std::underlying_type<index_mode>::type)lhs | (std::underlying_type<index_mode>::type)rhs);
94 }
95 
97 constexpr inline index_mode& operator|=(index_mode& lhs, index_mode rhs) noexcept { return lhs = lhs | rhs; }
98 
100 enum class query_search_mode {
101  normal = 0,
102  count_only = 1,
103  first_only = 1 << 1
104 };
105 
107 constexpr inline query_search_mode operator|(query_search_mode lhs, query_search_mode rhs) noexcept {
108  return (query_search_mode)((std::underlying_type<query_search_mode>::type)lhs |
109  (std::underlying_type<query_search_mode>::type)rhs);
110 }
111 
113 constexpr inline query_search_mode& operator|=(query_search_mode& lhs, query_search_mode rhs) noexcept {
114  return lhs = lhs | rhs;
115 }
116 
118 constexpr inline query_search_mode operator&(query_search_mode lhs, query_search_mode rhs) noexcept {
119  return (query_search_mode)((std::underlying_type<query_search_mode>::type)lhs &
120  (std::underlying_type<query_search_mode>::type)rhs);
121 }
122 
124 constexpr inline query_search_mode& operator&=(query_search_mode& lhs, query_search_mode rhs) noexcept {
125  return lhs = lhs & rhs;
126 }
127 
129 enum class errc {
130  // Tokyo cabinet error codes
131  success,
132  thread_error,
135  no_permission,
138  open_error,
139  close_error,
140  trunc_error,
141  sync_error,
142  stat_error,
143  seek_error,
144  read_error,
145  write_error,
146  mmap_error,
147  lock_error,
148  unlink_error,
149  rename_error,
150  mkdir_error,
151  rmdir_error,
152  keep,
155  miscellaneous = 9999,
156  // EJDB error codes
157  invalid_collection_name = 9000,
158  invalid_bson = 9001,
159  invalid_bson_oid = 9002,
162  invalid_metadata = 9005,
163  invalid_field_path = 9006,
164  invalid_query_regex = 9007,
165  query_result_sort_error = 9008,
166  query_error = 9009,
167  query_update_failed = 9010,
168  query_elemmatch_limit = 9011,
170  query_invalid_action = 9013,
171  too_many_collections = 9014,
172  import_export_error = 9015,
173  json_parse_failed = 9016,
174  bson_too_large = 9017,
175  invalid_command = 9018
176 };
177 
179 std::error_code make_error_code(errc ecode) noexcept;
180 
181 } // namespace ejdb
182 
183 namespace std {
185 template <> struct is_error_code_enum<ejdb::errc> : public true_type {};
186 }
187 
188 namespace ejdb {
189 
195 struct EJPP_EXPORT db final {
197  db() noexcept = default;
198 
200  explicit operator bool() const noexcept;
201 
203  std::error_code error() const noexcept;
205  static std::error_code error(std::weak_ptr<EJDB>) noexcept;
206 
208  bool open(const std::string& path, db_mode mode, std::error_code& ec);
210  void open(const std::string& path, db_mode mode);
211 
213  bool is_open() const noexcept;
214 
216  bool close(std::error_code& ec) noexcept;
218  void close();
219 
221  collection get_collection(const std::string& name, std::error_code& ec) const;
223  collection get_collection(const std::string& name) const;
224 
226  collection create_collection(const std::string& name, std::error_code& ec);
228  collection create_collection(const std::string& name);
229 
231  bool remove_collection(const std::string& name, bool unlink_file, std::error_code& ec);
233  void remove_collection(const std::string& name, bool unlink_file);
234 
236  const std::vector<collection> get_collections() const;
237 
239  query create_query(const std::vector<char>& doc, std::error_code& ec);
241  query create_query(const std::vector<char>& doc);
242 
244  bool sync(std::error_code& ec) noexcept;
246  void sync();
247 
249  std::vector<char> metadata(std::error_code& ec);
251  std::vector<char> metadata();
252 
253  private:
254  std::shared_ptr<EJDB> m_db;
255 };
256 
262 namespace detail {
263 
267 template <query_search_mode flags>
268 using query_return_type = typename std::conditional<
270  typename std::conditional<(flags & query_search_mode::first_only) == query_search_mode::first_only,
271  std::vector<char>, std::vector<std::vector<char>>>::type>::type;
272 }
273 
283 struct EJPP_EXPORT collection final {
285  collection() noexcept = default;
286 
288  explicit operator bool() const noexcept;
289 
291  std::experimental::optional<std::array<char, 12>> save_document(const std::vector<char>& data, std::error_code& ec);
293  std::experimental::optional<std::array<char, 12>> save_document(const std::vector<char>& data, bool merge,
294  std::error_code& ec);
296  std::array<char, 12> save_document(const std::vector<char>& data, bool merge = false);
297 
299  std::vector<char> load_document(std::array<char, 12> oid, std::error_code& ec) const;
301  std::vector<char> load_document(std::array<char, 12> oid) const;
302 
304  bool remove_document(std::array<char, 12>, std::error_code& ec) noexcept;
306  void remove_document(std::array<char, 12>);
307 
309  bool set_index(const std::string& ipath, index_mode flags, std::error_code& ec);
311  void set_index(const std::string& ipath, index_mode flags);
312 
319  template <query_search_mode flags = query_search_mode::normal>
320  detail::query_return_type<flags> execute_query(const query&);
321 
323  std::vector<std::vector<char>> get_all();
324 
326  bool sync(std::error_code& ec) noexcept;
328  void sync();
329 
331  std::string name() const;
332 
333  struct transaction_t;
334 
336  transaction_t& transaction() noexcept;
337 
338  private:
339  friend struct db;
340  EJPP_LOCAL collection(std::weak_ptr<EJDB> m_db, EJCOLL* m_coll) noexcept;
341 
342  std::weak_ptr<EJDB> m_db;
343  EJCOLL* m_coll{nullptr};
344 
345  public:
362  struct transaction_t {
364  bool start() noexcept;
366  bool commit() noexcept;
368  bool abort() noexcept;
369 
371  bool in_transaction() const noexcept;
373  explicit operator bool() const noexcept;
374 
375  private:
376  explicit transaction_t(collection*) noexcept;
377  transaction_t(transaction_t&&) = default;
378  transaction_t& operator=(transaction_t&&) = default;
379  transaction_t(const transaction_t& b) = default;
380  transaction_t& operator=(const transaction_t&) = default;
381 
382  friend struct collection;
383  friend struct unique_transaction;
384  collection* m_collection;
385  std::weak_ptr<EJDB> m_db;
386  };
387 
388  private:
389  transaction_t m_transaction{this};
390 };
391 
392 #ifndef DOXYGEN_SHOULD_SKIP_THIS
393 extern template EJPP_EXPORT detail::query_return_type<query_search_mode::normal>
394 collection::execute_query<query_search_mode::normal>(const query& qry);
395 extern template EJPP_EXPORT detail::query_return_type<query_search_mode::count_only>
396 collection::execute_query<query_search_mode::count_only>(const query& qry);
397 extern template EJPP_EXPORT detail::query_return_type<query_search_mode::first_only>
398 collection::execute_query<query_search_mode::first_only>(const query& qry);
399 extern template EJPP_EXPORT detail::query_return_type<query_search_mode::count_only | query_search_mode::first_only>
400 collection::execute_query<query_search_mode::count_only | query_search_mode::first_only>(const query& qry);
401 #endif // DOXYGEN_SHOULD_SKIP_THIS
402 
412 struct EJPP_EXPORT query final {
414  query() noexcept = default;
415 
417  explicit operator bool() const noexcept;
418 
420  query& operator&=(const std::vector<char>&)&;
422  query&& operator&=(const std::vector<char>&)&&;
424  query& operator&=(query) & noexcept;
426  query&& operator&=(query) && noexcept;
427 
429  query& operator|=(const std::vector<char>&)&;
431  query&& operator|=(const std::vector<char>&)&&;
433  query& operator|=(query) & noexcept;
435  query&& operator|=(query) && noexcept;
436 
438  query& set_hints(const std::vector<char>&)&;
440  query&& set_hints(const std::vector<char>&)&&;
441 
442  private:
443  friend struct db;
444  friend struct collection;
445  EJPP_LOCAL query(std::weak_ptr<EJDB> m_db, EJQ* m_qry) noexcept;
446 
447  std::weak_ptr<EJDB> m_db;
448 
449  struct eqry_deleter {
450  void operator()(EJQ* ptr) const noexcept;
451  };
452  std::unique_ptr<EJQ, eqry_deleter> m_qry;
453 };
454 
459 
464 
478 struct EJPP_EXPORT unique_transaction {
480  unique_transaction() noexcept = default;
483 
488 
493 
495 
497  void start();
499  void commit();
501  void abort();
502 
504  collection::transaction_t* release() noexcept;
505 
507  bool owns_transaction() const noexcept;
509  explicit operator bool() const noexcept;
510 
511  private:
512  unique_transaction(const unique_transaction&) = delete;
513  unique_transaction& operator=(const unique_transaction&) = delete;
514 
515  collection::transaction_t* m_trans{nullptr};
516  bool m_owns{false};
517  std::shared_ptr<EJDB> m_db;
518 };
519 
526 struct EJPP_EXPORT transaction_guard : private unique_transaction {
529 };
530 
531 } // namespace ejdb
532 
533 #endif // EJDB_HPP
Exceeded the maximum number of collections per database.
Invalid bson object.
Only one $elemMatch allowed in the fieldpath.
errc
Error codes. Tokyo Cabinet errors up to errc::miscellaneous.
Definition: ejdb.hpp:129
Invalid ejdb command specified.
Default search mode.
constexpr query_search_mode operator&(query_search_mode lhs, query_search_mode rhs) noexcept
Allow bitwise-AND of query_search_mode.
Definition: ejdb.hpp:118
Main point of access to EJDB.
Definition: ejdb.hpp:195
Inconsistent database metadata.
existing record
std::error_code make_error_code(errc ecode) noexcept
Makes an std::error_code from an ejdb::errc.
Definition: ejdb.cpp:828
Tag type for expressing an adopted transaction.
Definition: ejdb.hpp:456
illegal transaction state
constexpr db_mode & operator|=(db_mode &lhs, db_mode rhs) noexcept
Allow bitwise-OR-assign of db_mode.
Definition: ejdb.hpp:77
action key in $do block can only be one of: $join.
constexpr db_mode operator|(db_mode lhs, db_mode rhs) noexcept
Allow bitwise-OR of db_mode.
Definition: ejdb.hpp:72
Invalid query control field starting with '$'.
Invalid collection name.
Result set sorting error.
$strand, $stror, $in, $nin, $bt keys requires not empty array value.
Create if db file not exists.
typename std::conditional< (flags &query_search_mode::count_only)==query_search_mode::count_only, uint32_t, typename std::conditional<(flags &query_search_mode::first_only)==query_search_mode::first_only, std::vector< char >, std::vector< std::vector< char >>>::type >::type query_return_type
Determine the correct return type for query flags.
Definition: ejdb.hpp:271
Lock without blocking.
Query generic error.
Defines an exception-safe wrapper around collection::transaction_t with unique ownership.
Definition: ejdb.hpp:478
Open as a reader.
Open as a writer.
index_mode
Index modes, index types.
Definition: ejdb.hpp:80
EJDB export/import error.
Fetch first record only.
query_search_mode
Query search mode flags.
Definition: ejdb.hpp:100
Tag type for expressing a transaction that only tries to start.
Definition: ejdb.hpp:458
invalid record header
Open without locking.
JSON parsing failed.
Synchronize every transaction.
Invalid field path value.
Drop index for all types.
Represents an EJDB transaction.
Definition: ejdb.hpp:362
Array token index.
threading error
Truncate db on open.
Simple collection::transaction_t wrapper for exception safe operation using RAII
Definition: ejdb.hpp:526
Class representing an EJDB query.
Definition: ejdb.hpp:412
constexpr query_search_mode & operator&=(query_search_mode &lhs, query_search_mode rhs) noexcept
Allow bitwise-AND-assign of query_search_mode.
Definition: ejdb.hpp:124
Invalid query regexp value.
constexpr adopt_transaction_t adopt_transaction
Tag constant for adopting a transaction.
Definition: ejdb.hpp:461
Invalid bson object id.
Optimize indexes.
Class representing an EJDB collection.
Definition: ejdb.hpp:283
db_mode
Database open modes.
Definition: ejdb.hpp:61
miscellaneous error
constexpr try_transaction_t try_transaction
Tag constant for trying to start a transaction.
Definition: ejdb.hpp:463
$fields hint cannot mix include and exclude fields.
Case insensitive string index.
BSON size is too big.