diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2024-01-24 17:03:38 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2024-01-24 17:03:38 +0300 |
commit | 0f1f6841ce5a50d5b315c24d796a2d8e2627d136 (patch) | |
tree | e16bbf9e23ca75a88b8af032c4e3ed299ca8db66 /libodb/odb/database.hxx | |
parent | 823026b58211a4166de06ac243d978dcb9930271 (diff) | |
parent | 26e36b3a9d7b49d46ecfa69b447482251acba8ac (diff) |
Merge branch 'libodb' into multi-package
Diffstat (limited to 'libodb/odb/database.hxx')
-rw-r--r-- | libodb/odb/database.hxx | 657 |
1 files changed, 657 insertions, 0 deletions
diff --git a/libodb/odb/database.hxx b/libodb/odb/database.hxx new file mode 100644 index 0000000..e18e8ee --- /dev/null +++ b/libodb/odb/database.hxx @@ -0,0 +1,657 @@ +// file : odb/database.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DATABASE_HXX +#define ODB_DATABASE_HXX + +#include <odb/pre.hxx> + +#include <odb/details/config.hxx> // ODB_CXX11 + +#include <map> +#include <string> +#include <memory> // std::auto_ptr, std::unique_ptr +#include <cstddef> // std::size_t + +#ifdef ODB_CXX11 +# include <utility> // std::move +# include <functional> // std::function +# include <type_traits> // std::enable_if, std::is_convertible +#endif + +#include <odb/traits.hxx> +#include <odb/forward.hxx> +#include <odb/schema-version.hxx> +#include <odb/query.hxx> +#include <odb/prepared-query.hxx> +#include <odb/result.hxx> +#include <odb/connection.hxx> +#include <odb/exceptions.hxx> + +#include <odb/details/export.hxx> +#include <odb/details/mutex.hxx> +#include <odb/details/c-string.hxx> +#include <odb/details/unique-ptr.hxx> +#include <odb/details/function-wrapper.hxx> +#include <odb/details/meta/answer.hxx> + +namespace odb +{ + class transaction_impl; + + class LIBODB_EXPORT database + { + public: + virtual + ~database (); + +#ifdef ODB_CXX11 + //database (database&&) = default; // VC 2013 + + // Note: noexcept is not specified since *_map_ (std::map) can throw. + // + database (database&& d) + : id_ (d.id_), + tracer_ (d.tracer_), + query_factory_map_ (std::move (d.query_factory_map_)), + mutex_ (std::move (d.mutex_)), + schema_version_map_ (std::move (d.schema_version_map_)), + schema_version_table_ (std::move (d.schema_version_table_)), + schema_version_seq_ (d.schema_version_seq_) + { + } +#endif + + private: + database (const database&); + database& operator= (const database&); + +#ifdef ODB_CXX11 + database& operator= (const database&&); +#endif + + // Object persistence API. + // + public: + // Make the object persistent. + // + template <typename T> + typename object_traits<T>::id_type + persist (T& object); + + template <typename T> + typename object_traits<T>::id_type + persist (const T& object); + + template <typename T> + typename object_traits<T>::id_type + persist (T* obj_ptr); + + template <typename T, template <typename> class P> + typename object_traits<T>::id_type + persist (const P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + typename object_traits<T>::id_type + persist (const P<T, A1>& obj_ptr); + + template <typename T, template <typename> class P> + typename object_traits<T>::id_type + persist (P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + typename object_traits<T>::id_type + persist (P<T, A1>& obj_ptr); + + template <typename T> + typename object_traits<T>::id_type + persist (const typename object_traits<T>::pointer_type& obj_ptr); + + // Bulk persist. Can be a range of references or pointers (including + // smart pointers) to objects. + // + template <typename I> + void + persist (I begin, I end, bool continue_failed = true); + + // Load an object. Throw object_not_persistent if not found. + // + template <typename T> + typename object_traits<T>::pointer_type + load (const typename object_traits<T>::id_type& id); + + template <typename T> + void + load (const typename object_traits<T>::id_type& id, T& object); + + // Load (or reload, if it is already loaded) a section of an object. + // + template <typename T> + void + load (T& object, section&); + + // Reload an object. + // + template <typename T> + void + reload (T& object); + + template <typename T> + void + reload (T* obj_ptr); + + template <typename T, template <typename> class P> + void + reload (const P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + void + reload (const P<T, A1>& obj_ptr); + + template <typename T, template <typename> class P> + void + reload (P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + void + reload (P<T, A1>& obj_ptr); + + template <typename T> + void + reload (const typename object_traits<T>::pointer_type& obj_ptr); + + // Loan an object if found. Return NULL/false if not found. + // + template <typename T> + typename object_traits<T>::pointer_type + find (const typename object_traits<T>::id_type& id); + + template <typename T> + bool + find (const typename object_traits<T>::id_type& id, T& object); + + // Update the state of a modified objects. + // + template <typename T> + void + update (T& object); + + template <typename T> + void + update (T* obj_ptr); + + template <typename T, template <typename> class P> + void + update (const P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + void + update (const P<T, A1>& obj_ptr); + + template <typename T, template <typename> class P> + void + update (P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + void + update (P<T, A1>& obj_ptr); + + template <typename T> + void + update (const typename object_traits<T>::pointer_type& obj_ptr); + + // Bulk update. Can be a range of references or pointers (including + // smart pointers) to objects. + // + template <typename I> + void + update (I begin, I end, bool continue_failed = true); + + // Update a section of an object. Throws section_not_loaded exception + // if section is not loaded. Note also that this function does not + // clear the changed flag if it is set. + // + template <typename T> + void + update (const T& object, const section&); + + // Make the object transient. Throw object_not_persistent if not + // found. + // + template <typename T> + void + erase (const typename object_traits<T>::id_type& id); + + template <typename T> + void + erase (T& object); + + template <typename T> + void + erase (T* obj_ptr); + + template <typename T, template <typename> class P> + void + erase (const P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + void + erase (const P<T, A1>& obj_ptr); + + template <typename T, template <typename> class P> + void + erase (P<T>& obj_ptr); + + template <typename T, typename A1, template <typename, typename> class P> + void + erase (P<T, A1>& obj_ptr); + + template <typename T> + void + erase (const typename object_traits<T>::pointer_type& obj_ptr); + + // Bulk erase. + // + template <typename T, typename I> + void + erase (I id_begin, I id_end, bool continue_failed = true); + + // Can be a range of references or pointers (including smart pointers) + // to objects. + // + template <typename I> + void + erase (I obj_begin, I obj_end, bool continue_failed = true); + + // Erase multiple objects matching a query predicate. + // + template <typename T> + unsigned long long + erase_query (); + + template <typename T> + unsigned long long + erase_query (const char*); + + template <typename T> + unsigned long long + erase_query (const std::string&); + + template <typename T> + unsigned long long + erase_query (const odb::query<T>&); + + // Query API. + // + template <typename T> + result<T> + query (bool cache = true); + + template <typename T> + result<T> + query (const char*, bool cache = true); + + template <typename T> + result<T> + query (const std::string&, bool cache = true); + + template <typename T> + result<T> + query (const odb::query<T>&, bool cache = true); + + // Query one API. + // + template <typename T> + typename result<T>::pointer_type + query_one (); + + template <typename T> + bool + query_one (T& object); + + template <typename T> + T + query_value (); + + template <typename T> + typename result<T>::pointer_type + query_one (const char*); + + template <typename T> + bool + query_one (const char*, T& object); + + template <typename T> + T + query_value (const char*); + + template <typename T> + typename result<T>::pointer_type + query_one (const std::string&); + + template <typename T> + bool + query_one (const std::string&, T& object); + + template <typename T> + T + query_value (const std::string&); + + template <typename T> + typename result<T>::pointer_type + query_one (const odb::query<T>&); + + template <typename T> + bool + query_one (const odb::query<T>&, T& object); + + template <typename T> + T + query_value (const odb::query<T>&); + + // Query preparation. + // + template <typename T> + prepared_query<T> + prepare_query (const char* name, const char*); + + template <typename T> + prepared_query<T> + prepare_query (const char* name, const std::string&); + + template <typename T> + prepared_query<T> + prepare_query (const char* name, const odb::query<T>&); + + template <typename T> + void + cache_query (const prepared_query<T>&); + +#ifdef ODB_CXX11 + template <typename T, typename P> + void + cache_query (const prepared_query<T>&, std::unique_ptr<P> params); +#else + template <typename T, typename P> + void + cache_query (const prepared_query<T>&, std::auto_ptr<P> params); +#endif + + template <typename T> + prepared_query<T> + lookup_query (const char* name); + + template <typename T, typename P> + prepared_query<T> + lookup_query (const char* name, P*& params); + + // Prepared query factory. + // + public: + typedef odb::connection connection_type; + + typedef void query_factory_type (const char* name, connection_type&); + typedef query_factory_type* query_factory_ptr; + typedef details::function_wrapper< + query_factory_type> query_factory_wrapper; + +#ifndef ODB_CXX11 + void + query_factory (const char* name, query_factory_ptr); +#else + template <typename F> + typename std::enable_if< + std::is_convertible< + F, std::function<query_factory_type>>::value, void>::type + query_factory (const char* name, F f) + { + query_factory (name, query_factory_wrapper (std::move (f))); + } +#endif + + bool + call_query_factory (const char* name, connection_type&) const; + + private: + void + query_factory (const char* name, query_factory_wrapper); + + // Native database statement execution. + // + public: + unsigned long long + execute (const char* statement); + + unsigned long long + execute (const std::string& statement); + + unsigned long long + execute (const char* statement, std::size_t length); + + // Transactions. + // + public: + virtual transaction_impl* + begin () = 0; + + // Connections. + // + public: + connection_ptr + connection (); + + // SQL statement tracing. + // + public: + typedef odb::tracer tracer_type; + + void + tracer (tracer_type&); + + void + tracer (tracer_type*); + + tracer_type* + tracer () const; + + // Database schema version. + // + public: + typedef odb::schema_version schema_version_type; + typedef odb::schema_version_migration schema_version_migration_type; + + schema_version_type + schema_version (const std::string& schema_name = "") const; + + bool + schema_migration (const std::string& schema_name = "") const; + + // Note that there is code that relies on the returned reference + // being valid until the version is changed or the database instance + // is destroyed. + // + const schema_version_migration_type& + schema_version_migration (const std::string& schema_name = "") const; + + // Set schema version and migration state manually. + // + // Note that the modifier API is not thread-safe. That is, you should + // not modify the schema version while other threads may be accessing + // or modifying the same information. + // + void + schema_version_migration (schema_version_type, + bool migration, + const std::string& schema_name = ""); + + void + schema_version_migration (const schema_version_migration_type&, + const std::string& schema_name = ""); + + // Set default schema version table for all the schema names. The table + // name should already be quoted if necessary. + // + void + schema_version_table (const std::string& table_name); + + // Set schema version table for a specific schema. + // + void + schema_version_table (const std::string& table_name, + const std::string& schema_name); + + // Schema version sequence number. It is incremented every time the + // schema version or migration flag is changed and can be used to + // detect overall version changes. The starting value is 1. + // + unsigned int + schema_version_sequence () const; + + protected: + struct schema_version_info: schema_version_migration_type + { + std::string version_table; + }; + + virtual const schema_version_info& + load_schema_version (const std::string& schema_name) const = 0; + + private: + const schema_version_info& + schema_version_migration_ (const std::string& schema_name) const; + + // Database id. + // + public: + database_id + id () const; + + protected: + database (database_id); + + protected: + virtual connection_type* + connection_ () = 0; + + protected: + template <typename T, database_id DB> + typename object_traits<T>::id_type + persist_ (T&); + + template <typename T, database_id DB> + typename object_traits<T>::id_type + persist_ (const typename object_traits<T>::pointer_type&); + + template <typename I, database_id DB> + void + persist_ (I, I, bool); + + template <typename I, typename T, database_id DB> + void + persist_ (I, I, bool, details::meta::no ptr); + + template <typename I, typename T, database_id DB> + void + persist_ (I, I, bool, details::meta::yes ptr); + + template <typename T, database_id DB> + typename object_traits<T>::pointer_type + load_ (const typename object_traits<T>::id_type&); + + template <typename T, database_id DB> + void + load_ (const typename object_traits<T>::id_type&, T&); + + template <typename T, database_id DB> + void + load_ (T&, section&); + + template <typename T, database_id DB> + void + reload_ (T&); + + template <typename T, database_id DB> + typename object_traits<T>::pointer_type + find_ (const typename object_traits<T>::id_type&); + + template <typename T, database_id DB> + bool + find_ (const typename object_traits<T>::id_type&, T&); + + template <typename T, database_id DB> + void + update_ (T&); + + template <typename T, database_id DB> + void + update_ (const typename object_traits<T>::pointer_type&); + + template <typename I, database_id DB> + void + update_ (I, I, bool); + + template <typename T, database_id DB> + void + update_ (const T&, const section&); + + template <typename T, database_id DB> + void + erase_ (const typename object_traits<T>::id_type&); + + template <typename T, database_id DB> + void + erase_ (T&); + + template <typename T, database_id DB> + void + erase_ (const typename object_traits<T>::pointer_type&); + + template <typename I, typename T, database_id DB> + void + erase_id_ (I, I, bool); + + template <typename I, database_id DB> + void + erase_object_ (I, I, bool); + + template <typename T, database_id DB, typename Q> + typename result<T>::pointer_type + query_one_ (const Q&); + + template <typename T, database_id DB, typename Q> + bool + query_one_ (const Q&, T&); + + template <typename T, database_id DB, typename Q> + T + query_value_ (const Q&); + + template <typename T, + database_id DB, + class_kind kind = class_traits<T>::kind> + struct query_; + + protected: + typedef + std::map<const char*, query_factory_wrapper, details::c_string_comparator> + query_factory_map; + + typedef std::map<std::string, schema_version_info> schema_version_map; + + database_id id_; + tracer_type* tracer_; + query_factory_map query_factory_map_; + + details::unique_ptr<details::mutex> mutex_; // Dynamic for move support. + mutable schema_version_map schema_version_map_; + std::string schema_version_table_; + unsigned int schema_version_seq_; + }; +} + +#include <odb/database.ixx> +#include <odb/database.txx> + +#include <odb/post.hxx> + +#endif // ODB_DATABASE_HXX |