OSDN Git Service

Initial commit
[gikomona/GikoMona.git] / core / include / database.hpp
1 #ifndef GIKOMONA_CORE_DATABASE_HPP
2 #define GIKOMONA_CORE_DATABASE_HPP
3
4 #include <memory>
5
6 #include <sqlite3.h>
7
8 #include <boost/filesystem.hpp>
9
10 #include "GikoMona.hpp"
11 #include "query.hpp"
12
13 namespace monazilla { namespace GikoMona { namespace core {
14
15 class database final {
16 public:
17     template <typename T>
18     class sql_executer final {
19         friend database;
20         
21         sql_executer(const mona_string& sql) {}
22         ~sql_executer() {}
23         
24     public:
25         void operator()() {}
26     };
27
28 public:
29     typedef ::sqlite3 *db_object_type;
30     typedef database self_type;
31
32     database() : database("") {}
33     
34     /// @breif すでに存在するデータベースファイルを開く。まだファイルが存在しない場合は、新たに作成する。
35     database(const boost::filesystem::path& db_path) {
36         if(db_path.empty()) {
37             is_opened_db = false;
38         } else {
39             if(!boost::filesystem::exists(db_path)) {
40                 create(db_path);
41             } else {
42                 open(db_path);
43             }
44         }
45     }
46     
47     database(const self_type& other) = delete;
48     
49     ~database() { close(); }
50     
51     /// @breif 受け取った SQL を実行する。ただし、実行できる文は返り値の無いものに限られる。
52     /**
53      * @return SQL が正常に実行された場合は true、それ以外の場合は false を返す。
54      * @note この関数は SQL の実行結果を返さない。したがって、実行結果が必要な場合は、
55      *       compile_sql() を用いるべきである。
56      */
57     bool run_sql(const mona_string& sql) {
58         return (::sqlite3_exec(db, sql.c_str(), NULL, NULL, NULL) != SQLITE_OK)
59             ? false : true;
60     }
61     
62     /// @breif 受け取った SQL を sql_executer へと変換して返す。
63     /**
64      * @note 返された sql_executer を実行することで、ここで渡した SQL の実行結果を得ることができる。
65      *       実行した SQL の実行結果が不要である (あるいはそもそも実行結果が無い) 場合は、
66      *       run_sql() を用いるべきである。
67      */
68     template <typename T>
69     sql_executer<T> compile_sql(const mona_string& sql) {
70         return sql_executer<T>(sql);
71     }
72     
73     /// @brief すでに存在するデータベースファイルを開く。
74     bool open(const boost::filesystem::path& db_path) {
75         if (is_opened_db) {
76             close();
77         }
78         
79         is_opened_db =
80             (::sqlite3_open(db_path.c_str(), &db) != SQLITE_OK)
81                 ? false : true;
82         
83         return is_opened_db;
84     }
85     
86     /// @breif まだ存在しないデータベースファイルを新たに作成する。
87     /**
88      * @return true: ファイルが存在せず、かつ新たにデータベースファイルを作成することに成功した
89      *         false: ファイルが存在する、あるいは存在しないが新規データベースファイルの作成に失敗した
90      */
91     bool create(const boost::filesystem::path& db_path) {
92         if(boost::filesystem::exists(db_path)) {
93             return false;
94         }
95         
96         return open(db_path);
97     }
98     
99     void close() noexcept {
100         ::sqlite3_close(db);
101     }
102
103 private:
104     db_object_type db;
105     bool is_opened_db;
106     
107     void begin_sql_statement() { run_sql("begin;"); }
108     void end_sql_statement() { run_sql("end"); }
109 };
110
111 template <>
112 struct is_responsible_to_query<database> : public boost::mpl::true_ {};
113
114 } } }
115
116 #endif