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