summary refs log tree commit diff stats
path: root/lib/adverb_query.cpp
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2017-01-16 18:02:50 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2017-01-16 18:02:50 -0500
commit6746da6edd7d9d50efe374eabbb79a3cac882d81 (patch)
treeff20917e08b08d36b9541c1371106596e7bec442 /lib/adverb_query.cpp
parent4af7e55733098ca42f75a4ffaca1b0f6bab4dd36 (diff)
downloadverbly-6746da6edd7d9d50efe374eabbb79a3cac882d81.tar.gz
verbly-6746da6edd7d9d50efe374eabbb79a3cac882d81.tar.bz2
verbly-6746da6edd7d9d50efe374eabbb79a3cac882d81.zip
Started structural rewrite
The new object structure was designed to build on the existing WordNet
structure, while also adding in all of the data that we get from other sources.
More information about this can be found on the project wiki.

The generator has already been completely rewritten to generate a
datafile that uses the new structure. In addition, a number of indexes
are created, which does double the size of the datafile, but also allows
for much faster lookups. Finally, the new generator is written modularly
and is a lot more readable than the old one.

The verbly interface to the new object structure has mostly been
completed, but has not been tested fully. There is a completely new
search API which utilizes a lot of operator overloading; documentation
on how to use it should go up at some point.

Token processing and verb frames are currently unimplemented. Source for
these have been left in the repository for now.
Diffstat (limited to 'lib/adverb_query.cpp')
-rw-r--r--lib/adverb_query.cpp758
1 files changed, 0 insertions, 758 deletions
diff --git a/lib/adverb_query.cpp b/lib/adverb_query.cpp deleted file mode 100644 index 3e62bb7..0000000 --- a/lib/adverb_query.cpp +++ /dev/null
@@ -1,758 +0,0 @@
1#include "verbly.h"
2
3namespace verbly {
4
5 adverb_query::adverb_query(const data& _data) : _data(_data)
6 {
7
8 }
9
10 adverb_query& adverb_query::limit(int _limit)
11 {
12 if ((_limit > 0) || (_limit == unlimited))
13 {
14 this->_limit = _limit;
15 }
16
17 return *this;
18 }
19
20 adverb_query& adverb_query::random()
21 {
22 this->_random = true;
23
24 return *this;
25 }
26
27 adverb_query& adverb_query::except(const adverb& _word)
28 {
29 _except.push_back(_word);
30
31 return *this;
32 }
33
34 adverb_query& adverb_query::rhymes_with(const word& _word)
35 {
36 for (auto rhyme : _word.get_rhymes())
37 {
38 _rhymes.push_back(rhyme);
39 }
40
41 if (dynamic_cast<const adverb*>(&_word) != nullptr)
42 {
43 _except.push_back(dynamic_cast<const adverb&>(_word));
44 }
45
46 return *this;
47 }
48
49 adverb_query& adverb_query::rhymes_with(rhyme _r)
50 {
51 _rhymes.push_back(_r);
52
53 return *this;
54 }
55
56 adverb_query& adverb_query::has_pronunciation()
57 {
58 this->_has_prn = true;
59
60 return *this;
61 }
62
63 adverb_query& adverb_query::has_rhyming_noun()
64 {
65 _has_rhyming_noun = true;
66
67 return *this;
68 }
69
70 adverb_query& adverb_query::has_rhyming_adjective()
71 {
72 _has_rhyming_adjective = true;
73
74 return *this;
75 }
76
77 adverb_query& adverb_query::has_rhyming_adverb()
78 {
79 _has_rhyming_adverb = true;
80
81 return *this;
82 }
83
84 adverb_query& adverb_query::has_rhyming_verb()
85 {
86 _has_rhyming_verb = true;
87
88 return *this;
89 }
90
91 adverb_query& adverb_query::requires_comparative_form()
92 {
93 _requires_comparative_form = true;
94
95 return *this;
96 }
97
98 adverb_query& adverb_query::requires_superlative_form()
99 {
100 _requires_superlative_form = true;
101
102 return *this;
103 }
104
105 adverb_query& adverb_query::with_stress(filter<std::vector<bool>> _arg)
106 {
107 _stress = _arg;
108
109 return *this;
110 }
111
112 adverb_query& adverb_query::with_prefix(filter<std::string> _f)
113 {
114 _f.clean();
115 _with_prefix = _f;
116
117 return *this;
118 }
119
120 adverb_query& adverb_query::with_suffix(filter<std::string> _f)
121 {
122 _f.clean();
123 _with_suffix = _f;
124
125 return *this;
126 }
127
128 adverb_query& adverb_query::with_complexity(int _arg)
129 {
130 _with_complexity = _arg;
131
132 return *this;
133 }
134
135 adverb_query& adverb_query::has_antonyms()
136 {
137 _has_antonyms = true;
138
139 return *this;
140 }
141
142 adverb_query& adverb_query::antonym_of(filter<adverb> _f)
143 {
144 _f.clean();
145 _antonym_of = _f;
146
147 return *this;
148 }
149
150 adverb_query& adverb_query::has_synonyms()
151 {
152 _has_synonyms = true;
153
154 return *this;
155 }
156
157 adverb_query& adverb_query::synonym_of(filter<adverb> _f)
158 {
159 _f.clean();
160 _synonym_of = _f;
161
162 return *this;
163 }
164
165 adverb_query& adverb_query::is_mannernymic()
166 {
167 _is_mannernymic = true;
168
169 return *this;
170 }
171
172 adverb_query& adverb_query::mannernym_of(filter<adjective> _f)
173 {
174 _f.clean();
175 _mannernym_of = _f;
176
177 return *this;
178 }
179 /*
180 adverb_query& adverb_query::derived_from(const word& _w)
181 {
182 if (dynamic_cast<const adjective*>(&_w) != nullptr)
183 {
184 _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
185 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
186 {
187 _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
188 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
189 {
190 _derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
191 }
192
193 return *this;
194 }
195
196 adverb_query& adverb_query::not_derived_from(const word& _w)
197 {
198 if (dynamic_cast<const adjective*>(&_w) != nullptr)
199 {
200 _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
201 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
202 {
203 _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
204 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
205 {
206 _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
207 }
208
209 return *this;
210 }
211 */
212 std::list<adverb> adverb_query::run() const
213 {
214 std::stringstream construct;
215 construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs";
216 std::list<std::string> conditions;
217 std::list<binding> bindings;
218
219 if (_has_prn)
220 {
221 conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)");
222 }
223
224 if (!_rhymes.empty())
225 {
226 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
227 std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
228 conditions.push_back(cond);
229
230 for (auto rhy : _rhymes)
231 {
232 bindings.emplace_back(rhy.get_prerhyme());
233 bindings.emplace_back(rhy.get_rhyme());
234 }
235 }
236
237 if (_has_rhyming_noun)
238 {
239 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
240 }
241
242 if (_has_rhyming_adjective)
243 {
244 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
245 }
246
247 if (_has_rhyming_adverb)
248 {
249 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.adverb_id != curp.adverb_id)");
250 }
251
252 if (_has_rhyming_verb)
253 {
254 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
255 }
256
257 for (auto except : _except)
258 {
259 conditions.push_back("adverb_id != ?");
260 bindings.emplace_back(except._id);
261 }
262
263 if (_requires_comparative_form)
264 {
265 conditions.push_back("comparative IS NOT NULL");
266 }
267
268 if (_requires_superlative_form)
269 {
270 conditions.push_back("superlative IS NOT NULL");
271 }
272
273 if (!_stress.empty())
274 {
275 std::stringstream cond;
276 if (_stress.get_notlogic())
277 {
278 cond << "adverb_id NOT IN";
279 } else {
280 cond << "adverb_id IN";
281 }
282
283 cond << "(SELECT adverb_id FROM adverb_pronunciations WHERE ";
284
285 std::function<std::string (filter<std::vector<bool>>, bool)> recur = [&] (filter<std::vector<bool>> f, bool notlogic) -> std::string {
286 switch (f.get_type())
287 {
288 case filter<std::vector<bool>>::type::singleton:
289 {
290 std::ostringstream _val;
291 for (auto syl : f.get_elem())
292 {
293 if (syl)
294 {
295 _val << "1";
296 } else {
297 _val << "0";
298 }
299 }
300
301 bindings.emplace_back(_val.str());
302
303 if (notlogic == f.get_notlogic())
304 {
305 return "stress = ?";
306 } else {
307 return "stress != ?";
308 }
309 }
310
311 case filter<std::vector<bool>>::type::group:
312 {
313 bool truelogic = notlogic != f.get_notlogic();
314
315 std::list<std::string> clauses;
316 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::vector<bool>> f2) {
317 return recur(f2, truelogic);
318 });
319
320 if (truelogic == f.get_orlogic())
321 {
322 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
323 } else {
324 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
325 }
326 }
327 }
328 };
329
330 cond << recur(_stress, _stress.get_notlogic());
331 cond << ")";
332 conditions.push_back(cond.str());
333 }
334
335 if (!_with_prefix.empty())
336 {
337 std::function<std::string (filter<std::string>, bool)> recur = [&] (filter<std::string> f, bool notlogic) -> std::string {
338 switch (f.get_type())
339 {
340 case filter<std::string>::type::singleton:
341 {
342 bindings.emplace_back(f.get_elem() + "%");
343
344 if (notlogic == f.get_notlogic())
345 {
346 return "base_form LIKE ?";
347 } else {
348 return "base_form NOT LIKE ?";
349 }
350 }
351
352 case filter<std::string>::type::group:
353 {
354 bool truelogic = notlogic != f.get_notlogic();
355
356 std::list<std::string> clauses;
357 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::string> f2) {
358 return recur(f2, truelogic);
359 });
360
361 if (truelogic == f.get_orlogic())
362 {
363 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
364 } else {
365 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
366 }
367 }
368 }
369 };
370
371 conditions.push_back(recur(_with_prefix, false));
372 }
373
374 if (!_with_suffix.empty())
375 {
376 std::function<std::string (filter<std::string>, bool)> recur = [&] (filter<std::string> f, bool notlogic) -> std::string {
377 switch (f.get_type())
378 {
379 case filter<std::string>::type::singleton:
380 {
381 bindings.emplace_back("%" + f.get_elem());
382
383 if (notlogic == f.get_notlogic())
384 {
385 return "base_form LIKE ?";
386 } else {
387 return "base_form NOT LIKE ?";
388 }
389 }
390
391 case filter<std::string>::type::group:
392 {
393 bool truelogic = notlogic != f.get_notlogic();
394
395 std::list<std::string> clauses;
396 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::string> f2) {
397 return recur(f2, truelogic);
398 });
399
400 if (truelogic == f.get_orlogic())
401 {
402 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
403 } else {
404 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
405 }
406 }
407 }
408 };
409
410 conditions.push_back(recur(_with_suffix, false));
411 }
412
413 if (_with_complexity != unlimited)
414 {
415 conditions.push_back("complexity = ?");
416 bindings.emplace_back(_with_complexity);
417 }
418
419 if (_has_antonyms)
420 {
421 conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)");
422 }
423
424 if (!_antonym_of.empty())
425 {
426 std::stringstream cond;
427 if (_antonym_of.get_notlogic())
428 {
429 cond << "adverb_id NOT IN";
430 } else {
431 cond << "adverb_id IN";
432 }
433
434 cond << "(SELECT adverb_2_id FROM adverb_antonymy WHERE ";
435
436 std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string {
437 switch (f.get_type())
438 {
439 case filter<adverb>::type::singleton:
440 {
441 bindings.emplace_back(f.get_elem()._id);
442
443 if (notlogic == f.get_notlogic())
444 {
445 return "adverb_1_id = ?";
446 } else {
447 return "adverb_1_id != ?";
448 }
449 }
450
451 case filter<adverb>::type::group:
452 {
453 bool truelogic = notlogic != f.get_notlogic();
454
455 std::list<std::string> clauses;
456 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) {
457 return recur(f2, truelogic);
458 });
459
460 if (truelogic == f.get_orlogic())
461 {
462 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
463 } else {
464 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
465 }
466 }
467 }
468 };
469
470 cond << recur(_antonym_of, _antonym_of.get_notlogic());
471 cond << ")";
472 conditions.push_back(cond.str());
473 }
474
475 if (_has_synonyms)
476 {
477 conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)");
478 }
479
480 if (!_synonym_of.empty())
481 {
482 std::stringstream cond;
483 if (_antonym_of.get_notlogic())
484 {
485 cond << "adverb_id NOT IN";
486 } else {
487 cond << "adverb_id IN";
488 }
489
490 cond << "(SELECT adverb_2_id FROM adverb_synonymy WHERE ";
491
492 std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string {
493 switch (f.get_type())
494 {
495 case filter<adverb>::type::singleton:
496 {
497 bindings.emplace_back(f.get_elem()._id);
498
499 if (notlogic == f.get_notlogic())
500 {
501 return "adverb_1_id = ?";
502 } else {
503 return "adverb_1_id != ?";
504 }
505 }
506
507 case filter<adverb>::type::group:
508 {
509 bool truelogic = notlogic != f.get_notlogic();
510
511 std::list<std::string> clauses;
512 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) {
513 return recur(f2, truelogic);
514 });
515
516 if (truelogic == f.get_orlogic())
517 {
518 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
519 } else {
520 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
521 }
522 }
523 }
524 };
525
526 cond << recur(_synonym_of, _synonym_of.get_notlogic());
527 cond << ")";
528 conditions.push_back(cond.str());
529 }
530
531 if (_is_mannernymic)
532 {
533 conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)");
534 }
535
536 if (!_mannernym_of.empty())
537 {
538 std::stringstream cond;
539 if (_antonym_of.get_notlogic())
540 {
541 cond << "adverb_id NOT IN";
542 } else {
543 cond << "adverb_id IN";
544 }
545
546 cond << "(SELECT mannernym_id FROM mannernymy WHERE ";
547
548 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
549 switch (f.get_type())
550 {
551 case filter<adjective>::type::singleton:
552 {
553 bindings.emplace_back(f.get_elem()._id);
554
555 if (notlogic == f.get_notlogic())
556 {
557 return "adjective_id = ?";
558 } else {
559 return "adjective_id != ?";
560 }
561 }
562
563 case filter<adjective>::type::group:
564 {
565 bool truelogic = notlogic != f.get_notlogic();
566
567 std::list<std::string> clauses;
568 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
569 return recur(f2, truelogic);
570 });
571
572 if (truelogic == f.get_orlogic())
573 {
574 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
575 } else {
576 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
577 }
578 }
579 }
580 };
581
582 cond << recur(_mannernym_of, _mannernym_of.get_notlogic());
583 cond << ")";
584 conditions.push_back(cond.str());
585 }
586
587/* if (!_derived_from_adjective.empty())
588 {
589 std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ");
590 std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
591 conditions.push_back(cond);
592 }
593
594 if (!_not_derived_from_adjective.empty())
595 {
596 std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ");
597 std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
598 conditions.push_back(cond);
599 }
600
601 if (!_derived_from_adverb.empty())
602 {
603 std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV");
604 std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
605 conditions.push_back(cond);
606 }
607
608 if (!_not_derived_from_adverb.empty())
609 {
610 std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV");
611 std::string cond = "adverb_id NOT IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
612 conditions.push_back(cond);
613 }
614
615 if (!_derived_from_noun.empty())
616 {
617 std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN");
618 std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
619 conditions.push_back(cond);
620 }
621
622 if (!_not_derived_from_noun.empty())
623 {
624 std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN");
625 std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
626 conditions.push_back(cond);
627 }*/
628
629 if (!conditions.empty())
630 {
631 construct << " WHERE ";
632 construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND ");
633 }
634
635 if (_random)
636 {
637 construct << " ORDER BY RANDOM()";
638 }
639
640 if (_limit != unlimited)
641 {
642 construct << " LIMIT " << _limit;
643 }
644
645 sqlite3_stmt* ppstmt;
646 std::string query = construct.str();
647 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
648 {
649 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
650 }
651
652 int i = 1;
653 for (auto& binding : bindings)
654 {
655 switch (binding.get_type())
656 {
657 case binding::type::integer:
658 {
659 sqlite3_bind_int(ppstmt, i, binding.get_integer());
660
661 break;
662 }
663
664 case binding::type::string:
665 {
666 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
667
668 break;
669 }
670 }
671
672 i++;
673 }
674
675 /*
676 for (auto adj : _derived_from_adjective)
677 {
678 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id);
679 }
680
681 for (auto adj : _not_derived_from_adjective)
682 {
683 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id);
684 }
685
686 for (auto adv : _derived_from_adverb)
687 {
688 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id);
689 }
690
691 for (auto adv : _not_derived_from_adverb)
692 {
693 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id);
694 }
695
696 for (auto n : _derived_from_noun)
697 {
698 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id);
699 }
700
701 for (auto n : _not_derived_from_noun)
702 {
703 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id);
704 }*/
705
706 std::list<adverb> output;
707 while (sqlite3_step(ppstmt) == SQLITE_ROW)
708 {
709 adverb tnc {_data, sqlite3_column_int(ppstmt, 0)};
710 tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
711
712 if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL)
713 {
714 tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
715 }
716
717 if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL)
718 {
719 tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3)));
720 }
721
722 output.push_back(tnc);
723 }
724
725 sqlite3_finalize(ppstmt);
726
727 for (auto& adverb : output)
728 {
729 query = "SELECT pronunciation, prerhyme, rhyme FROM adverb_pronunciations WHERE adverb_id = ?";
730 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
731 {
732 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
733 }
734
735 sqlite3_bind_int(ppstmt, 1, adverb._id);
736
737 while (sqlite3_step(ppstmt) == SQLITE_ROW)
738 {
739 std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0)));
740 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
741
742 adverb.pronunciations.push_back(phonemes);
743
744 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
745 {
746 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
747 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
748 adverb.rhymes.emplace_back(prerhyme, rhyming);
749 }
750 }
751
752 sqlite3_finalize(ppstmt);
753 }
754
755 return output;
756 }
757
758};