summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--src/seclude.h124
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
9namespace 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 */