-rw-r--r-- | src/db.cc | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/db.cc b/src/db.cc new file mode 100644 index 0000000..d1e0a85 --- a/dev/null +++ b/src/db.cc | |||
@@ -0,0 +1,101 @@ | |||
1 | #include <unistd.h> | ||
2 | #include <sys/stat.h> | ||
3 | #include <sys/types.h> | ||
4 | #include <cassert> | ||
5 | #include <napkin/exception.h> | ||
6 | #include "db.h" | ||
7 | |||
8 | #include "config.h" | ||
9 | |||
10 | namespace napkin { | ||
11 | |||
12 | extern const char *sql_bootstrap; | ||
13 | |||
14 | db_t::db_t() { | ||
15 | const char *h = getenv("HOME"); | ||
16 | if(h) { | ||
17 | datadir = h; | ||
18 | datadir += "/."PACKAGE_NAME"/"; | ||
19 | }else{ | ||
20 | char *cwd = get_current_dir_name(); | ||
21 | if(!cwd) | ||
22 | throw napkin::exception("failed to get_current_dir_name()"); | ||
23 | datadir = cwd; | ||
24 | free(cwd); | ||
25 | datadir += "/."PACKAGE_NAME"/"; | ||
26 | } | ||
27 | if(access(datadir.c_str(),R_OK|W_OK) | ||
28 | && mkdir(datadir.c_str(),0700)) | ||
29 | throw napkin::exception("no access to '"+datadir+"' directory"); | ||
30 | open((datadir+PACKAGE_NAME".db").c_str()); | ||
31 | assert(_D); | ||
32 | char **resp; int nr,nc; char *errm; | ||
33 | if(sqlite3_get_table( | ||
34 | _D, | ||
35 | "SELECT s_tobed FROM sleeps LIMIT 0", | ||
36 | &resp,&nr,&nc,&errm)!=SQLITE_OK) { | ||
37 | if(sqlite3_exec(_D,sql_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) | ||
38 | throw napkin::exception(string("failed to bootstrap sqlite database: ")+errm); | ||
39 | }else | ||
40 | sqlite3_free_table(resp); | ||
41 | } | ||
42 | |||
43 | void db_t::store(const hypnodata_t& hd) { | ||
44 | sqlite::mem_t<char*> S = sqlite3_mprintf( | ||
45 | "INSERT INTO sleeps (" | ||
46 | "s_tobed,s_alarm," | ||
47 | "s_window,s_data_a," | ||
48 | "s_almost_awakes," | ||
49 | "s_timezone" | ||
50 | ") VALUES (" | ||
51 | "%Q,%Q,%d,%d,%Q,%ld" | ||
52 | ")", | ||
53 | hd.w3c_to_bed().c_str(), | ||
54 | hd.w3c_alarm().c_str(), | ||
55 | hd.window,hd.data_a, | ||
56 | hd.w3c_almostawakes().c_str(), | ||
57 | timezone ); | ||
58 | try { | ||
59 | exec(S); | ||
60 | }catch(sqlite::exception& se) { | ||
61 | if(se.rcode==SQLITE_CONSTRAINT) | ||
62 | throw exception_db_already("The record seems to be already in the database"); | ||
63 | throw exception_db("Well, some error occured"); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | void db_t::remove(const hypnodata_t& hd) { | ||
68 | sqlite::mem_t<char*> S = sqlite3_mprintf( | ||
69 | "DELETE FROM sleeps" | ||
70 | " WHERE s_tobed=%Q AND s_alarm=%Q", | ||
71 | hd.w3c_to_bed().c_str(), | ||
72 | hd.w3c_alarm().c_str() ); | ||
73 | exec(S); | ||
74 | } | ||
75 | |||
76 | void db_t::load(list<hypnodata_ptr_t>& rv, | ||
77 | const string& sql) { | ||
78 | sqlite::table_t T; | ||
79 | int nr,nc; | ||
80 | get_table( string( | ||
81 | "SELECT" | ||
82 | " s_tobed, s_alarm," | ||
83 | " s_window, s_data_a," | ||
84 | " s_almost_awakes" | ||
85 | " FROM sleeps" | ||
86 | " "+sql).c_str(),T,&nr,&nc ); | ||
87 | if(nr) { | ||
88 | assert(nc==5); | ||
89 | for(int r=1;r<=nr;++r) { | ||
90 | hypnodata_ptr_t hd(new hypnodata_t()); | ||
91 | hd->set_to_bed(T.get(r,0,nc)); | ||
92 | hd->set_alarm(T.get(r,1,nc)); | ||
93 | hd->set_window(T.get(r,2,nc)); | ||
94 | hd->set_data_a(T.get(r,3,nc)); | ||
95 | hd->set_almost_awakes(T.get(r,4,nc)); | ||
96 | rv.push_back(hd); | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | } | ||