-rw-r--r-- | src/seclude.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/seclude.h b/src/seclude.h new file mode 100644 index 0000000..cab3699 --- a/dev/null +++ b/src/seclude.h | |||
@@ -0,0 +1,124 @@ | |||
1 | #ifndef __SECLUDE_H | ||
2 | #define __SECLUDE_H | ||
3 | |||
4 | #include <sqlite3.h> | ||
5 | #include <stdexcept> | ||
6 | #include <tr1/memory> | ||
7 | #include <cstdarg> | ||
8 | |||
9 | namespace seclude { | ||
10 | using std::tr1::shared_ptr; | ||
11 | |||
12 | static struct sql_null_type { } sql_null; | ||
13 | |||
14 | |||
15 | struct sqlite3_error : public std::runtime_error { | ||
16 | int code, ecode; | ||
17 | sqlite3_error(sqlite3 *s,const std::string& m) | ||
18 | : std::runtime_error(m+": "+(s?sqlite3_errmsg(s):"unknown error")), | ||
19 | code(s?sqlite3_errcode(s):-1), ecode(s?sqlite3_extended_errcode(s):-1) { } | ||
20 | sqlite3_error(sqlite3_stmt *s,const std::string& m) | ||
21 | : std::runtime_error(m+": "+(s?sqlite3_errmsg(sqlite3_db_handle(s)):"unknown error")), | ||
22 | code(s?sqlite3_errcode(sqlite3_db_handle(s)):-1), | ||
23 | ecode(s?sqlite3_extended_errcode(sqlite3_db_handle(s)):-1) { } | ||
24 | }; | ||
25 | |||
26 | |||
27 | static void sqlite3_stmt_deleter(sqlite3_stmt* s) { s && sqlite3_finalize(s); } | ||
28 | struct stmt_t : public shared_ptr<sqlite3_stmt> { | ||
29 | stmt_t(sqlite3_stmt *s) : shared_ptr<sqlite3_stmt>(s,sqlite3_stmt_deleter) { } | ||
30 | |||
31 | bool step() { | ||
32 | switch(sqlite3_step(get())) { | ||
33 | case SQLITE_DONE: return false; | ||
34 | case SQLITE_ROW: return true; | ||
35 | } | ||
36 | panic("failed to sqlite3_step()"); | ||
37 | } | ||
38 | stmt_t& reset() { | ||
39 | return worry(sqlite3_reset(get()),"failed to sqlite3_reset()"); | ||
40 | } | ||
41 | stmt_t& clear_bindings() { | ||
42 | return worry(sqlite3_clear_bindings(get()),"failed to sqlite3_clear_bindings()"); | ||
43 | } | ||
44 | int data_count() { return sqlite3_data_count(get()); } | ||
45 | int column_count() { return sqlite3_column_count(get()); } | ||
46 | template<typename T> T column(int i); | ||
47 | std::string column_name(int i) { return sqlite3_column_name(get(),i); } | ||
48 | int column_type(int i) { return sqlite3_column_type(get(),i); } | ||
49 | bool is_column_null(int i) { return column_type(i)==SQLITE_NULL; } | ||
50 | |||
51 | template<typename T> int bind_(int i,T v); | ||
52 | template<typename T> | ||
53 | stmt_t& bind(int i,T v) { | ||
54 | return worry(bind_(i,v),"failed to perform binding"); | ||
55 | } | ||
56 | template<typename T> | ||
57 | stmt_t& bind(const char *n,T v) { return bind(bind_parameter_index(n),v); } | ||
58 | int bind_parameter_index(const char *n) { | ||
59 | int rv = sqlite3_bind_parameter_index(get(),n); | ||
60 | if(!rv) throw std::invalid_argument("failed to sqlite3_bind_parameter_index()"); | ||
61 | return rv; | ||
62 | } | ||
63 | |||
64 | |||
65 | stmt_t& worry(int c,const char *m) { if(c!=SQLITE_OK) panic(m); return *this;} | ||
66 | stmt_t& panic(const std::string& m) { throw sqlite3_error(get(),m); return *this;} | ||
67 | }; | ||
68 | |||
69 | template<> inline int stmt_t::bind_<int>(int i,int v) { | ||
70 | return sqlite3_bind_int(get(),i,v); } | ||
71 | template<> inline int stmt_t::bind_<long>(int i,long v) { | ||
72 | return sqlite3_bind_int64(get(),i,v); } | ||
73 | template<> inline int stmt_t::bind_<sqlite3_int64>(int i,sqlite3_int64 v) { | ||
74 | return sqlite3_bind_int64(get(),i,v); } | ||
75 | template<> inline int stmt_t::bind_<double>(int i,double v) { | ||
76 | return sqlite3_bind_double(get(),i,v); } | ||
77 | template<> inline int stmt_t::bind_<const std::string&>(int i,const std::string& v) { | ||
78 | return sqlite3_bind_text(get(),i,v.c_str(),-1,SQLITE_TRANSIENT); } | ||
79 | template<> inline int stmt_t::bind_<std::string>(int i,std::string v) { | ||
80 | return sqlite3_bind_text(get(),i,v.c_str(),-1,SQLITE_TRANSIENT); } | ||
81 | template<> inline int stmt_t::bind_<const char *>(int i,const char *v) { | ||
82 | return sqlite3_bind_text(get(),i,v,-1,SQLITE_TRANSIENT); } | ||
83 | template<> inline int stmt_t::bind_<sql_null_type>(int i,sql_null_type) { | ||
84 | return sqlite3_bind_null(get(),i); } | ||
85 | |||
86 | template<> int stmt_t::column<int>(int i) { return sqlite3_column_int(get(),i); } | ||
87 | template<> long stmt_t::column<long>(int i) { return sqlite3_column_int64(get(),i); } | ||
88 | template<> sqlite3_int64 stmt_t::column<sqlite3_int64>(int i) { return sqlite3_column_int64(get(),i); } | ||
89 | template<> double stmt_t::column<double>(int i) { return sqlite3_column_double(get(),i); } | ||
90 | template<> std::string stmt_t::column<std::string>(int i) { return (const char*)sqlite3_column_text(get(),i); } | ||
91 | |||
92 | |||
93 | static void sqlite3_deleter(sqlite3* s) { s && sqlite3_close(s); } | ||
94 | struct db_t : public shared_ptr<sqlite3> { | ||
95 | db_t(const char *f) { | ||
96 | sqlite3 *s=0; | ||
97 | int c = sqlite3_open(f,&s); | ||
98 | reset(s,sqlite3_deleter); | ||
99 | worry(c,"failed to sqlite3_open()"); | ||
100 | } | ||
101 | |||
102 | void exec(const char *s) { | ||
103 | char *e = 0; | ||
104 | int c = sqlite3_exec(get(),s,NULL,NULL,&e); | ||
105 | if(e) sqlite3_free(e); | ||
106 | worry(c,"failed to sqlite3_exec()"); | ||
107 | } | ||
108 | |||
109 | stmt_t prepare(const char *s) { | ||
110 | sqlite3_stmt *r=0; | ||
111 | int c = sqlite3_prepare(get(),s,-1,&r,0); | ||
112 | stmt_t rv(r); | ||
113 | worry(c,"failed to sqlite3_prepare()"); | ||
114 | return rv; | ||
115 | } | ||
116 | |||
117 | int changes() { return sqlite3_changes(get()); } | ||
118 | |||
119 | void worry(int c,const char *m) { if(c!=SQLITE_OK) throw sqlite3_error(get(),m); } | ||
120 | }; | ||
121 | |||
122 | } | ||
123 | |||
124 | #endif /* __SECLUDE_H */ | ||