summary refs log tree commit diff stats
path: root/lib/query.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/query.h')
-rw-r--r--lib/query.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/query.h b/lib/query.h new file mode 100644 index 0000000..e31be3d --- /dev/null +++ b/lib/query.h
@@ -0,0 +1,123 @@
1#ifndef QUERY_H_7CC5284C
2#define QUERY_H_7CC5284C
3
4#include <vector>
5#include <stdexcept>
6#include <string>
7#include <list>
8#include <sqlite3.h>
9#include <iostream>
10#include "statement.h"
11#include "binding.h"
12
13namespace verbly {
14
15 class database_error : public std::logic_error {
16 public:
17
18 database_error(std::string msg, std::string sqlMsg) : std::logic_error(msg + " (" + sqlMsg + ")")
19 {
20 }
21 };
22
23 template <typename Object>
24 class query {
25 public:
26
27 query(const database& db, sqlite3* ppdb, filter queryFilter, bool random, int limit) : db_(&db)
28 {
29 statement stmt(Object::objectType, std::move(queryFilter));
30
31 std::string queryString = stmt.getQueryString(Object::select, random, limit);
32 std::list<binding> bindings = stmt.getBindings();
33
34 std::cout << queryString << std::endl;
35
36 if (sqlite3_prepare_v2(ppdb, queryString.c_str(), queryString.length(), &ppstmt_, NULL) != SQLITE_OK)
37 {
38 std::string errorMsg = sqlite3_errmsg(ppdb);
39 sqlite3_finalize(ppstmt_);
40
41 throw database_error("Error preparing query", errorMsg);
42 }
43
44 int i = 1;
45 for (const binding& value : bindings)
46 {
47 switch (value.getType())
48 {
49 case binding::type::integer:
50 {
51 if (sqlite3_bind_int(ppstmt_, i, value.getInteger()) != SQLITE_OK)
52 {
53 std::string errorMsg = sqlite3_errmsg(ppdb);
54 sqlite3_finalize(ppstmt_);
55
56 throw database_error("Error binding value to query", errorMsg);
57 }
58
59 break;
60 }
61
62 case binding::type::string:
63 {
64 if (sqlite3_bind_text(ppstmt_, i, value.getString().c_str(), value.getString().length(), SQLITE_TRANSIENT) != SQLITE_OK)
65 {
66 std::string errorMsg = sqlite3_errmsg(ppdb);
67 sqlite3_finalize(ppstmt_);
68
69 throw database_error("Error binding value to query", errorMsg);
70 }
71
72 break;
73 }
74
75 case binding::type::invalid:
76 {
77 throw std::logic_error("Cannot use invalid bindings");
78 }
79 }
80
81 i++;
82 }
83 }
84
85 ~query()
86 {
87 sqlite3_finalize(ppstmt_);
88 }
89
90 std::vector<Object> all() const
91 {
92 std::vector<Object> result;
93
94 while (sqlite3_step(ppstmt_) == SQLITE_ROW)
95 {
96 result.emplace_back(*db_, ppstmt_);
97 }
98
99 sqlite3_reset(ppstmt_);
100
101 return result;
102 }
103
104 Object first() const
105 {
106 std::vector<Object> results = all();
107 if (!results.empty())
108 {
109 return results.front();
110 } else {
111 throw std::logic_error("query returned empty dataset");
112 }
113 }
114
115 private:
116 const database* db_;
117 sqlite3_stmt* ppstmt_;
118
119 };
120
121};
122
123#endif /* end of include guard: QUERY_H_7CC5284C */