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.h107
1 files changed, 29 insertions, 78 deletions
diff --git a/lib/query.h b/lib/query.h index 0f490ed..65b4e9d 100644 --- a/lib/query.h +++ b/lib/query.h
@@ -5,10 +5,8 @@
5#include <stdexcept> 5#include <stdexcept>
6#include <string> 6#include <string>
7#include <list> 7#include <list>
8#include <sqlite3.h> 8#include <hkutil/database.h>
9#include <iostream>
10#include "statement.h" 9#include "statement.h"
11#include "binding.h"
12#include "order.h" 10#include "order.h"
13 11
14namespace verbly { 12namespace verbly {
@@ -16,7 +14,10 @@ namespace verbly {
16 class database_error : public std::logic_error { 14 class database_error : public std::logic_error {
17 public: 15 public:
18 16
19 database_error(std::string msg, std::string sqlMsg) : std::logic_error(msg + " (" + sqlMsg + ")") 17 database_error(
18 std::string msg,
19 std::string sqlMsg) :
20 std::logic_error(msg + " (" + sqlMsg + ")")
20 { 21 {
21 } 22 }
22 }; 23 };
@@ -25,107 +26,57 @@ namespace verbly {
25 class query { 26 class query {
26 public: 27 public:
27 28
28 query(const database& db, sqlite3* ppdb, filter queryFilter, order sortOrder, int limit) : db_(&db) 29 query(
30 const database& db,
31 hatkirby::database& ppdb,
32 filter queryFilter,
33 order sortOrder,
34 int limit) :
35 db_(db),
36 ppdb_(ppdb)
29 { 37 {
30 if ((sortOrder.getType() == order::type::field) 38 if ((sortOrder.getType() == order::type::field)
31 && (sortOrder.getSortField().getObject() != Object::objectType)) 39 && (sortOrder.getSortField().getObject() != Object::objectType))
32 { 40 {
33 throw std::invalid_argument("Can only sort query by a field in the result table"); 41 throw std::invalid_argument(
42 "Can only sort query by a field in the result table");
34 } 43 }
35 44
36 statement stmt(Object::objectType, std::move(queryFilter)); 45 statement stmt(Object::objectType, std::move(queryFilter));
37 46
38 std::string queryString = stmt.getQueryString(Object::select, std::move(sortOrder), limit); 47 queryString_ =
39 std::list<binding> bindings = stmt.getBindings(); 48 stmt.getQueryString(Object::select, std::move(sortOrder), limit);
40 49
41 if (sqlite3_prepare_v2(ppdb, queryString.c_str(), queryString.length(), &ppstmt_, NULL) != SQLITE_OK) 50 bindings_ = stmt.getBindings();
42 {
43 std::string errorMsg = sqlite3_errmsg(ppdb);
44 sqlite3_finalize(ppstmt_);
45
46 throw database_error("Error preparing query", errorMsg);
47 }
48
49 int i = 1;
50 for (const binding& value : bindings)
51 {
52 switch (value.getType())
53 {
54 case binding::type::integer:
55 {
56 if (sqlite3_bind_int(ppstmt_, i, value.getInteger()) != SQLITE_OK)
57 {
58 std::string errorMsg = sqlite3_errmsg(ppdb);
59 sqlite3_finalize(ppstmt_);
60
61 throw database_error("Error binding value to query", errorMsg);
62 }
63
64 break;
65 }
66
67 case binding::type::string:
68 {
69 if (sqlite3_bind_text(ppstmt_, i, value.getString().c_str(), value.getString().length(), SQLITE_TRANSIENT) != SQLITE_OK)
70 {
71 std::string errorMsg = sqlite3_errmsg(ppdb);
72 sqlite3_finalize(ppstmt_);
73
74 throw database_error("Error binding value to query", errorMsg);
75 }
76
77 break;
78 }
79
80 case binding::type::invalid:
81 {
82 throw std::logic_error("Cannot use invalid bindings");
83 }
84
85 case binding::type::field:
86 {
87 throw std::logic_error("Compare field binding made it past statement generation");
88 }
89 }
90
91 i++;
92 }
93 }
94
95 ~query()
96 {
97 sqlite3_finalize(ppstmt_);
98 } 51 }
99 52
100 std::vector<Object> all() const 53 std::vector<Object> all() const
101 { 54 {
55 std::vector<hatkirby::row> rows =
56 ppdb_.queryAll(queryString_, bindings_);
57
102 std::vector<Object> result; 58 std::vector<Object> result;
103 59
104 while (sqlite3_step(ppstmt_) == SQLITE_ROW) 60 for (hatkirby::row& r : rows)
105 { 61 {
106 result.emplace_back(*db_, ppstmt_); 62 result.emplace_back(db_, std::move(r));
107 } 63 }
108 64
109 sqlite3_reset(ppstmt_);
110
111 return result; 65 return result;
112 } 66 }
113 67
114 Object first() const 68 Object first() const
115 { 69 {
116 std::vector<Object> results = all(); 70 return { db_, ppdb_.queryFirst(queryString_, bindings_) };
117 if (!results.empty())
118 {
119 return results.front();
120 } else {
121 throw std::logic_error("query returned empty dataset");
122 }
123 } 71 }
124 72
125 private: 73 private:
126 const database* db_;
127 sqlite3_stmt* ppstmt_;
128 74
75 const database& db_;
76 hatkirby::database& ppdb_;
77
78 std::string queryString_;
79 std::list<hatkirby::binding> bindings_;
129 }; 80 };
130 81
131}; 82};