OSDN Git Service

[core] :
[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, typename ...U>
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     /// @brief すでに存在するデータベースファイルを開く。まだファイルが存在しない場合は、新たに作成する。
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     /// @brief 受け取った 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     }
60     
61     /// @brief 受け取った SQL を sql_executer へと変換して返す。
62     /**
63      * @note 返された sql_executer を実行することで、ここで渡した SQL の実行結果を得ることができる。
64      *       実行した SQL の実行結果が不要である (あるいはそもそも実行結果が無い) 場合は、
65      *       run_sql() を用いるべきである。
66      */
67     template <typename T, typename ...U>
68     sql_executer<T, U...> compile_sql(const mona_string& sql) {
69         return sql_executer<T>(sql);
70     }
71     
72     template <typename ...ValueType>
73     void insert(const mona_string& into,
74                 const std::tuple<ValueType...>& value) {}
75     
76     template <typename T>
77     T select(const mona_string& column,
78              const mona_string& from) const noexcept {}
79     
80     template <typename ...ValueType>
81     std::tuple<ValueType...>
82     select_all(const mona_string& from) const noexcept {}
83     
84     /// @brief データベースの最適化を行う。
85     /**
86      * @note 内部では以下のコマンドが実行され、データベースの不要データの圧縮と再構築が行われる。
87      *       VACUUM; REINDEX;
88      */
89     void optimize() {
90         run_sql("VACUUM;");
91         run_sql("REINDEX;");
92     }
93     
94     /// @brief すでに存在するデータベースファイルを開く。
95     bool open(const boost::filesystem::path& db_path) {
96         if (is_opened_db) {
97             close();
98         } else if (!boost::filesystem::exists(db_path)) {
99             is_opened_db = false;
100             return is_opened_db;
101         }
102         
103         is_opened_db = (::sqlite3_open(db_path.c_str(), &db) != SQLITE_OK);
104         
105         return is_opened_db;
106     }
107     
108     /// @brief まだ存在しないデータベースファイルを新たに作成する。
109     /**
110      * @retval true ファイルが存在せず、かつ新たにデータベースファイルを作成することに成功した
111      *         false ファイルが存在する、あるいは存在しないが新規データベースファイルの作成に失敗した
112      */
113     bool create(const boost::filesystem::path& db_path) {
114         if(boost::filesystem::exists(db_path)) {
115             return false;
116         }
117         
118         return open(db_path);
119     }
120     
121     /// @brief 開いていたデータベースファイルを閉じる。
122     void close() noexcept {
123         ::sqlite3_close(db);
124     }
125
126 private:
127     db_object_type db;
128     bool is_opened_db;
129     
130     void begin_sql_statement() { run_sql("BEGIN;"); }
131     void end_sql_statement() { run_sql("END;"); }
132 };
133
134 template <>
135 struct is_responsible_to_query<database> : public boost::mpl::true_ {};
136
137 } } }
138
139 #endif