summary refs log tree commit diff stats
path: root/lib/verb_query.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/verb_query.cpp')
-rw-r--r--lib/verb_query.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/lib/verb_query.cpp b/lib/verb_query.cpp new file mode 100644 index 0000000..173a04e --- /dev/null +++ b/lib/verb_query.cpp
@@ -0,0 +1,170 @@
1#include "verbly.h"
2
3namespace verbly {
4
5 verb_query::verb_query(const data& _data) : _data(_data)
6 {
7
8 }
9
10 verb_query& verb_query::limit(int _limit)
11 {
12 if ((_limit > 0) || (_limit == unlimited))
13 {
14 this->_limit = _limit;
15 }
16
17 return *this;
18 }
19
20 verb_query& verb_query::random()
21 {
22 this->_random = true;
23
24 return *this;
25 }
26
27 verb_query& verb_query::except(const verb& _word)
28 {
29 _except.push_back(_word);
30
31 return *this;
32 }
33
34 verb_query& verb_query::rhymes_with(const word& _word)
35 {
36 for (auto rhyme : _word.rhyme_phonemes())
37 {
38 _rhymes.push_back(rhyme);
39 }
40
41 if (dynamic_cast<const verb*>(&_word) != nullptr)
42 {
43 _except.push_back(dynamic_cast<const verb&>(_word));
44 }
45
46 return *this;
47 }
48
49 verb_query& verb_query::has_pronunciation()
50 {
51 this->_has_prn = true;
52
53 return *this;
54 }
55
56 verb_query& verb_query::has_frames()
57 {
58 this->_has_frames = true;
59
60 return *this;
61 }
62
63 std::list<verb> verb_query::run() const
64 {
65 std::stringstream construct;
66 construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs";
67 std::list<std::string> conditions;
68
69 if (_has_prn)
70 {
71 conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)");
72 }
73
74 if (!_rhymes.empty())
75 {
76 std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN");
77 std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
78 conditions.push_back(cond);
79 }
80
81 for (auto except : _except)
82 {
83 conditions.push_back("verb_id != @EXCID");
84 }
85
86 if (!_has_frames)
87 {
88 conditions.push_back("verb_id IN (SELECT verb_id FROM verb_groups)");
89 }
90
91 if (!conditions.empty())
92 {
93 construct << " WHERE ";
94 construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND ");
95 }
96
97 if (_random)
98 {
99 construct << " ORDER BY RANDOM()";
100 }
101
102 if (_limit != unlimited)
103 {
104 construct << " LIMIT " << _limit;
105 }
106
107 sqlite3_stmt* ppstmt;
108 std::string query = construct.str();
109 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
110 {
111 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
112 }
113
114 if (!_rhymes.empty())
115 {
116 int i = 0;
117 for (auto rhyme : _rhymes)
118 {
119 std::string rhymer = "%" + rhyme;
120 sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC);
121
122 i++;
123 }
124 }
125
126 for (auto except : _except)
127 {
128 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id);
129 }
130
131 std::list<verb> output;
132 while (sqlite3_step(ppstmt) == SQLITE_ROW)
133 {
134 verb tnc {_data, sqlite3_column_int(ppstmt, 0)};
135 tnc._infinitive = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
136 tnc._past_tense = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
137 tnc._past_participle = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3)));
138 tnc._ing_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4)));
139 tnc._s_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 5)));
140
141 output.push_back(tnc);
142 }
143
144 sqlite3_finalize(ppstmt);
145
146 for (auto& verb : output)
147 {
148 query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?";
149 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
150 {
151 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
152 }
153
154 sqlite3_bind_int(ppstmt, 1, verb._id);
155
156 while (sqlite3_step(ppstmt) == SQLITE_ROW)
157 {
158 std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0)));
159 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
160
161 verb.pronunciations.push_back(phonemes);
162 }
163
164 sqlite3_finalize(ppstmt);
165 }
166
167 return output;
168 }
169
170};