summary refs log tree commit diff stats
path: root/lib/noun_query.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/noun_query.cpp')
-rw-r--r--lib/noun_query.cpp2013
1 files changed, 0 insertions, 2013 deletions
diff --git a/lib/noun_query.cpp b/lib/noun_query.cpp deleted file mode 100644 index 8648227..0000000 --- a/lib/noun_query.cpp +++ /dev/null
@@ -1,2013 +0,0 @@
1#include "verbly.h"
2
3namespace verbly {
4
5 noun_query::noun_query(const data& _data) : _data(_data)
6 {
7
8 }
9
10 noun_query& noun_query::limit(int _limit)
11 {
12 if ((_limit > 0) || (_limit == unlimited))
13 {
14 this->_limit = _limit;
15 }
16
17 return *this;
18 }
19
20 noun_query& noun_query::random()
21 {
22 this->_random = true;
23
24 return *this;
25 }
26
27 noun_query& noun_query::except(const noun& _word)
28 {
29 _except.push_back(_word);
30
31 return *this;
32 }
33
34 noun_query& noun_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 noun*>(&_word) != nullptr)
42 {
43 _except.push_back(dynamic_cast<const noun&>(_word));
44 }
45
46 return *this;
47 }
48
49 noun_query& noun_query::rhymes_with(rhyme _r)
50 {
51 _rhymes.push_back(_r);
52
53 return *this;
54 }
55
56 noun_query& noun_query::has_pronunciation()
57 {
58 this->_has_prn = true;
59
60 return *this;
61 }
62
63 noun_query& noun_query::has_rhyming_noun()
64 {
65 _has_rhyming_noun = true;
66
67 return *this;
68 }
69
70 noun_query& noun_query::has_rhyming_adjective()
71 {
72 _has_rhyming_adjective = true;
73
74 return *this;
75 }
76
77 noun_query& noun_query::has_rhyming_adverb()
78 {
79 _has_rhyming_adverb = true;
80
81 return *this;
82 }
83
84 noun_query& noun_query::has_rhyming_verb()
85 {
86 _has_rhyming_verb = true;
87
88 return *this;
89 }
90
91 noun_query& noun_query::with_stress(filter<std::vector<bool>> _arg)
92 {
93 _stress = _arg;
94
95 return *this;
96 }
97
98 noun_query& noun_query::with_singular_form(std::string _arg)
99 {
100 _with_singular_form.push_back(_arg);
101
102 return *this;
103 }
104
105 noun_query& noun_query::with_prefix(filter<std::string> _f)
106 {
107 _f.clean();
108 _with_prefix = _f;
109
110 return *this;
111 }
112
113 noun_query& noun_query::with_suffix(filter<std::string> _f)
114 {
115 _f.clean();
116 _with_suffix = _f;
117
118 return *this;
119 }
120
121 noun_query& noun_query::requires_plural_form()
122 {
123 _requires_plural_form = true;
124
125 return *this;
126 }
127
128 noun_query& noun_query::with_complexity(int _arg)
129 {
130 _with_complexity = _arg;
131
132 return *this;
133 }
134
135 noun_query& noun_query::is_hypernym()
136 {
137 _is_hypernym = true;
138
139 return *this;
140 }
141
142 noun_query& noun_query::hypernym_of(filter<noun> _f)
143 {
144 _f.clean();
145 _hypernym_of = _f;
146
147 return *this;
148 }
149
150 noun_query& noun_query::full_hypernym_of(filter<noun> _f)
151 {
152 _f.clean();
153 _full_hypernym_of = _f;
154
155 return *this;
156 }
157
158 noun_query& noun_query::is_hyponym()
159 {
160 _is_hyponym = true;
161
162 return *this;
163 }
164
165 noun_query& noun_query::hyponym_of(filter<noun> _f)
166 {
167 _f.clean();
168 _hyponym_of = _f;
169
170 return *this;
171 }
172
173 noun_query& noun_query::full_hyponym_of(filter<noun> _f)
174 {
175 _f.clean();
176 _full_hyponym_of = _f;
177
178 return *this;
179 }
180
181 noun_query& noun_query::is_part_meronym()
182 {
183 _is_part_meronym = true;
184
185 return *this;
186 }
187
188 noun_query& noun_query::part_meronym_of(filter<noun> _f)
189 {
190 _f.clean();
191 _part_meronym_of = _f;
192
193 return *this;
194 }
195
196 noun_query& noun_query::full_part_meronym_of(filter<noun> _f)
197 {
198 _f.clean();
199 _full_part_meronym_of = _f;
200
201 return *this;
202 }
203
204 noun_query& noun_query::is_part_holonym()
205 {
206 _is_part_holonym = true;
207
208 return *this;
209 }
210
211 noun_query& noun_query::part_holonym_of(filter<noun> _f)
212 {
213 _f.clean();
214 _part_holonym_of = _f;
215
216 return *this;
217 }
218
219 noun_query& noun_query::full_part_holonym_of(filter<noun> _f)
220 {
221 _f.clean();
222 _full_part_holonym_of = _f;
223
224 return *this;
225 }
226
227 noun_query& noun_query::is_substance_meronym()
228 {
229 _is_substance_meronym = true;
230
231 return *this;
232 }
233
234 noun_query& noun_query::substance_meronym_of(filter<noun> _f)
235 {
236 _f.clean();
237 _substance_meronym_of = _f;
238
239 return *this;
240 }
241
242 noun_query& noun_query::full_substance_meronym_of(filter<noun> _f)
243 {
244 _f.clean();
245 _full_substance_meronym_of = _f;
246
247 return *this;
248 }
249
250 noun_query& noun_query::is_substance_holonym()
251 {
252 _is_substance_holonym = true;
253
254 return *this;
255 }
256
257 noun_query& noun_query::substance_holonym_of(filter<noun> _f)
258 {
259 _f.clean();
260 _substance_holonym_of = _f;
261
262 return *this;
263 }
264
265 noun_query& noun_query::full_substance_holonym_of(filter<noun> _f)
266 {
267 _f.clean();
268 _full_substance_holonym_of = _f;
269
270 return *this;
271 }
272
273 noun_query& noun_query::is_member_meronym()
274 {
275 _is_member_meronym = true;
276
277 return *this;
278 }
279
280 noun_query& noun_query::member_meronym_of(filter<noun> _f)
281 {
282 _f.clean();
283 _member_meronym_of = _f;
284
285 return *this;
286 }
287
288 noun_query& noun_query::full_member_meronym_of(filter<noun> _f)
289 {
290 _f.clean();
291 _full_member_meronym_of = _f;
292
293 return *this;
294 }
295
296 noun_query& noun_query::is_member_holonym()
297 {
298 _is_member_holonym = true;
299
300 return *this;
301 }
302
303 noun_query& noun_query::member_holonym_of(filter<noun> _f)
304 {
305 _f.clean();
306 _member_holonym_of = _f;
307
308 return *this;
309 }
310
311 noun_query& noun_query::full_member_holonym_of(filter<noun> _f)
312 {
313 _f.clean();
314 _full_member_holonym_of = _f;
315
316 return *this;
317 }
318
319 noun_query& noun_query::is_proper()
320 {
321 _is_proper = true;
322
323 return *this;
324 }
325
326 noun_query& noun_query::is_not_proper()
327 {
328 _is_not_proper = true;
329
330 return *this;
331 }
332
333 noun_query& noun_query::is_instance()
334 {
335 _is_instance = true;
336
337 return *this;
338 }
339
340 noun_query& noun_query::instance_of(filter<noun> _f)
341 {
342 _f.clean();
343 _instance_of = _f;
344
345 return *this;
346 }
347
348 noun_query& noun_query::is_class()
349 {
350 _is_class = true;
351
352 return *this;
353 }
354
355 noun_query& noun_query::class_of(filter<noun> _f)
356 {
357 _f.clean();
358 _class_of = _f;
359
360 return *this;
361 }
362
363 noun_query& noun_query::has_synonyms()
364 {
365 _has_synonyms = true;
366
367 return *this;
368 }
369
370 noun_query& noun_query::synonym_of(filter<noun> _f)
371 {
372 _f.clean();
373 _synonym_of = _f;
374
375 return *this;
376 }
377
378 noun_query& noun_query::has_antonyms()
379 {
380 _has_antonyms = true;
381
382 return *this;
383 }
384
385 noun_query& noun_query::antonym_of(filter<noun> _f)
386 {
387 _f.clean();
388 _antonym_of = _f;
389
390 return *this;
391 }
392
393 noun_query& noun_query::has_pertainym()
394 {
395 _has_pertainym = true;
396
397 return *this;
398 }
399
400 noun_query& noun_query::anti_pertainym_of(filter<adjective> _f)
401 {
402 _f.clean();
403 _anti_pertainym_of = _f;
404
405 return *this;
406 }
407
408 noun_query& noun_query::is_attribute()
409 {
410 _is_attribute = true;
411
412 return *this;
413 }
414
415 noun_query& noun_query::attribute_of(filter<adjective> _f)
416 {
417 _f.clean();
418 _attribute_of = _f;
419
420 return *this;
421 }
422
423 noun_query& noun_query::at_least_n_images(int _arg)
424 {
425 _at_least_n_images = _arg;
426
427 return *this;
428 }
429
430 noun_query& noun_query::with_wnid(int _arg)
431 {
432 _with_wnid.insert(_arg);
433
434 return *this;
435 }
436
437 /*
438 noun_query& noun_query::derived_from(const word& _w)
439 {
440 if (dynamic_cast<const adjective*>(&_w) != nullptr)
441 {
442 _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
443 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
444 {
445 _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
446 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
447 {
448 _derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
449 }
450
451 return *this;
452 }
453
454 noun_query& noun_query::not_derived_from(const word& _w)
455 {
456 if (dynamic_cast<const adjective*>(&_w) != nullptr)
457 {
458 _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
459 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
460 {
461 _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
462 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
463 {
464 _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
465 }
466
467 return *this;
468 }*/
469
470 std::list<noun> noun_query::run() const
471 {
472 std::stringstream construct;
473
474 if (!_full_hypernym_of.empty() || !_full_hyponym_of.empty() || !_full_part_meronym_of.empty() || !_full_part_holonym_of.empty() || !_full_substance_meronym_of.empty() || !_full_substance_holonym_of.empty() || !_full_member_meronym_of.empty() || !_full_member_holonym_of.empty())
475 {
476 construct << "WITH RECURSIVE ";
477
478 std::list<std::string> ctes;
479
480 for (auto hyponym : _full_hypernym_of.uniq_flatten())
481 {
482 ctes.push_back("hypernym_tree_" + std::to_string(hyponym._id) + " AS (SELECT hypernym_id FROM hypernymy WHERE hyponym_id = " + std::to_string(hyponym._id) + " UNION SELECT h.hypernym_id FROM hypernym_tree_" + std::to_string(hyponym._id) + " AS t INNER JOIN hypernymy AS h ON t.hypernym_id = h.hyponym_id)");
483 }
484
485 for (auto hypernym : _full_hyponym_of.uniq_flatten())
486 {
487 ctes.push_back("hyponym_tree_" + std::to_string(hypernym._id) + " AS (SELECT hyponym_id FROM hypernymy WHERE hypernym_id = " + std::to_string(hypernym._id) + " UNION SELECT h.hyponym_id FROM hyponym_tree_" + std::to_string(hypernym._id) + " AS t INNER JOIN hypernymy AS h ON t.hyponym_id = h.hypernym_id)");
488 }
489
490 for (auto holonym : _full_part_meronym_of.uniq_flatten())
491 {
492 ctes.push_back("part_meronym_tree_" + std::to_string(holonym._id) + " AS (SELECT meronym_id FROM part_meronymy WHERE holonym_id = " + std::to_string(holonym._id) + " UNION SELECT h.meronym_id FROM part_meronym_tree_" + std::to_string(holonym._id) + " AS t INNER JOIN part_meronymy AS h ON t.meronym_id = h.holonym_id)");
493 }
494
495 for (auto meronym : _full_part_holonym_of.uniq_flatten())
496 {
497 ctes.push_back("part_holonym_tree_" + std::to_string(meronym._id) + " AS (SELECT holonym_id FROM part_meronymy WHERE meronym_id = " + std::to_string(meronym._id) + " UNION SELECT h.holonym_id FROM part_holonym_tree_" + std::to_string(meronym._id) + " AS t INNER JOIN part_meronymy AS h ON t.holonym_id = h.meronym_id)");
498 }
499
500 for (auto holonym : _full_substance_meronym_of.uniq_flatten())
501 {
502 ctes.push_back("substance_meronym_tree_" + std::to_string(holonym._id) + " AS (SELECT meronym_id FROM substance_meronymy WHERE holonym_id = " + std::to_string(holonym._id) + " UNION SELECT h.meronym_id FROM substance_meronym_tree_" + std::to_string(holonym._id) + " AS t INNER JOIN substance_meronymy AS h ON t.meronym_id = h.holonym_id)");
503 }
504
505 for (auto meronym : _full_substance_holonym_of.uniq_flatten())
506 {
507 ctes.push_back("substance_holonym_tree_" + std::to_string(meronym._id) + " AS (SELECT holonym_id FROM substance_meronymy WHERE meronym_id = " + std::to_string(meronym._id) + " UNION SELECT h.holonym_id FROM substance_holonym_tree_" + std::to_string(meronym._id) + " AS t INNER JOIN substance_meronymy AS h ON t.holonym_id = h.meronym_id)");
508 }
509
510 for (auto holonym : _full_member_meronym_of.uniq_flatten())
511 {
512 ctes.push_back("member_meronym_tree_" + std::to_string(holonym._id) + " AS (SELECT meronym_id FROM member_meronymy WHERE holonym_id = " + std::to_string(holonym._id) + " UNION SELECT h.meronym_id FROM member_meronym_tree_" + std::to_string(holonym._id) + " AS t INNER JOIN member_meronymy AS h ON t.meronym_id = h.holonym_id)");
513 }
514
515 for (auto meronym : _full_member_holonym_of.uniq_flatten())
516 {
517 ctes.push_back("member_holonym_tree_" + std::to_string(meronym._id) + " AS (SELECT holonym_id FROM member_meronymy WHERE meronym_id = " + std::to_string(meronym._id) + " UNION SELECT h.holonym_id FROM member_holonym_tree_" + std::to_string(meronym._id) + " AS t INNER JOIN member_meronymy AS h ON t.holonym_id = h.meronym_id)");
518 }
519
520 construct << verbly::implode(std::begin(ctes), std::end(ctes), ", ");
521 construct << " ";
522 }
523
524 construct << "SELECT noun_id, singular, plural, wnid FROM nouns";
525 std::list<std::string> conditions;
526 std::list<binding> bindings;
527
528 if (_has_prn)
529 {
530 conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)");
531 }
532
533 if (!_rhymes.empty())
534 {
535 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
536 std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
537 conditions.push_back(cond);
538
539 for (auto rhy : _rhymes)
540 {
541 bindings.emplace_back(rhy.get_prerhyme());
542 bindings.emplace_back(rhy.get_rhyme());
543 }
544 }
545
546 if (_has_rhyming_noun)
547 {
548 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.noun_id != curp.noun_id)");
549 }
550
551 if (_has_rhyming_adjective)
552 {
553 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
554 }
555
556 if (_has_rhyming_adverb)
557 {
558 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
559 }
560
561 if (_has_rhyming_verb)
562 {
563 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
564 }
565
566 if (!_stress.empty())
567 {
568 std::stringstream cond;
569 if (_stress.get_notlogic())
570 {
571 cond << "noun_id NOT IN";
572 } else {
573 cond << "noun_id IN";
574 }
575
576 cond << "(SELECT noun_id FROM noun_pronunciations WHERE ";
577
578 std::function<std::string (filter<std::vector<bool>>, bool)> recur = [&] (filter<std::vector<bool>> f, bool notlogic) -> std::string {
579 switch (f.get_type())
580 {
581 case filter<std::vector<bool>>::type::singleton:
582 {
583 std::ostringstream _val;
584 for (auto syl : f.get_elem())
585 {
586 if (syl)
587 {
588 _val << "1";
589 } else {
590 _val << "0";
591 }
592 }
593
594 bindings.emplace_back(_val.str());
595
596 if (notlogic == f.get_notlogic())
597 {
598 return "stress = ?";
599 } else {
600 return "stress != ?";
601 }
602 }
603
604 case filter<std::vector<bool>>::type::group:
605 {
606 bool truelogic = notlogic != f.get_notlogic();
607
608 std::list<std::string> clauses;
609 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::vector<bool>> f2) {
610 return recur(f2, truelogic);
611 });
612
613 if (truelogic == f.get_orlogic())
614 {
615 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
616 } else {
617 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
618 }
619 }
620 }
621 };
622
623 cond << recur(_stress, _stress.get_notlogic());
624 cond << ")";
625 conditions.push_back(cond.str());
626 }
627
628 for (auto except : _except)
629 {
630 conditions.push_back("noun_id != ?");
631 bindings.emplace_back(except._id);
632 }
633
634 if (!_with_singular_form.empty())
635 {
636 std::list<std::string> clauses(_with_singular_form.size(), "singular = ?");
637 std::string cond = "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
638 conditions.push_back(cond);
639
640 for (auto form : _with_singular_form)
641 {
642 bindings.emplace_back(form);
643 }
644 }
645
646 if (_requires_plural_form)
647 {
648 conditions.push_back("plural IS NOT NULL");
649 }
650
651 if (!_with_prefix.empty())
652 {
653 std::function<std::string (filter<std::string>, bool)> recur = [&] (filter<std::string> f, bool notlogic) -> std::string {
654 switch (f.get_type())
655 {
656 case filter<std::string>::type::singleton:
657 {
658 bindings.emplace_back(f.get_elem() + "%");
659
660 if (notlogic == f.get_notlogic())
661 {
662 return "singular LIKE ?";
663 } else {
664 return "singular NOT LIKE ?";
665 }
666 }
667
668 case filter<std::string>::type::group:
669 {
670 bool truelogic = notlogic != f.get_notlogic();
671
672 std::list<std::string> clauses;
673 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::string> f2) {
674 return recur(f2, truelogic);
675 });
676
677 if (truelogic == f.get_orlogic())
678 {
679 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
680 } else {
681 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
682 }
683 }
684 }
685 };
686
687 conditions.push_back(recur(_with_prefix, false));
688 }
689
690 if (!_with_suffix.empty())
691 {
692 std::function<std::string (filter<std::string>, bool)> recur = [&] (filter<std::string> f, bool notlogic) -> std::string {
693 switch (f.get_type())
694 {
695 case filter<std::string>::type::singleton:
696 {
697 bindings.emplace_back("%" + f.get_elem());
698
699 if (notlogic == f.get_notlogic())
700 {
701 return "singular LIKE ?";
702 } else {
703 return "singular NOT LIKE ?";
704 }
705 }
706
707 case filter<std::string>::type::group:
708 {
709 bool truelogic = notlogic != f.get_notlogic();
710
711 std::list<std::string> clauses;
712 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::string> f2) {
713 return recur(f2, truelogic);
714 });
715
716 if (truelogic == f.get_orlogic())
717 {
718 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
719 } else {
720 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
721 }
722 }
723 }
724 };
725
726 conditions.push_back(recur(_with_suffix, false));
727 }
728
729 if (_with_complexity != unlimited)
730 {
731 conditions.push_back("complexity = ?");
732 bindings.emplace_back(_with_complexity);
733 }
734
735 if (_is_hypernym)
736 {
737 conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)");
738 }
739
740 if (!_hypernym_of.empty())
741 {
742 std::stringstream cond;
743 if (_hypernym_of.get_notlogic())
744 {
745 cond << "noun_id NOT IN";
746 } else {
747 cond << "noun_id IN";
748 }
749
750 cond << "(SELECT hypernym_id FROM hypernymy WHERE ";
751
752 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
753 switch (f.get_type())
754 {
755 case filter<noun>::type::singleton:
756 {
757 bindings.emplace_back(f.get_elem()._id);
758
759 if (notlogic == f.get_notlogic())
760 {
761 return "hyponym_id = ?";
762 } else {
763 return "hyponym_id != ?";
764 }
765 }
766
767 case filter<noun>::type::group:
768 {
769 bool truelogic = notlogic != f.get_notlogic();
770
771 std::list<std::string> clauses;
772 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
773 return recur(f2, truelogic);
774 });
775
776 if (truelogic == f.get_orlogic())
777 {
778 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
779 } else {
780 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
781 }
782 }
783 }
784 };
785
786 cond << recur(_hypernym_of, _hypernym_of.get_notlogic());
787 cond << ")";
788 conditions.push_back(cond.str());
789 }
790
791 if (!_full_hypernym_of.empty())
792 {
793 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
794 switch (f.get_type())
795 {
796 case filter<noun>::type::singleton:
797 {
798 if (notlogic == f.get_notlogic())
799 {
800 return "noun_id IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")";
801 } else {
802 return "noun_id NOT IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")";
803 }
804 }
805
806 case filter<noun>::type::group:
807 {
808 bool truelogic = notlogic != f.get_notlogic();
809
810 std::list<std::string> clauses;
811 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
812 return recur(f2, truelogic);
813 });
814
815 if (truelogic == f.get_orlogic())
816 {
817 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
818 } else {
819 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
820 }
821 }
822 }
823 };
824
825 conditions.push_back(recur(_full_hypernym_of, false));
826 }
827
828 if (!_full_hyponym_of.empty())
829 {
830 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
831 switch (f.get_type())
832 {
833 case filter<noun>::type::singleton:
834 {
835 if (notlogic == f.get_notlogic())
836 {
837 return "noun_id IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")";
838 } else {
839 return "noun_id NOT IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")";
840 }
841 }
842
843 case filter<noun>::type::group:
844 {
845 bool truelogic = notlogic != f.get_notlogic();
846
847 std::list<std::string> clauses;
848 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
849 return recur(f2, truelogic);
850 });
851
852 if (truelogic == f.get_orlogic())
853 {
854 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
855 } else {
856 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
857 }
858 }
859 }
860 };
861
862 conditions.push_back(recur(_full_hyponym_of, false));
863 }
864
865 if (_is_hyponym)
866 {
867 conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)");
868 }
869
870 if (!_hyponym_of.empty())
871 {
872 std::stringstream cond;
873 if (_hyponym_of.get_notlogic())
874 {
875 cond << "noun_id NOT IN";
876 } else {
877 cond << "noun_id IN";
878 }
879
880 cond << "(SELECT hyponym_id FROM hypernymy WHERE ";
881
882 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
883 switch (f.get_type())
884 {
885 case filter<noun>::type::singleton:
886 {
887 bindings.emplace_back(f.get_elem()._id);
888
889 if (notlogic == f.get_notlogic())
890 {
891 return "hypernym_id = ?";
892 } else {
893 return "hypernym_id != ?";
894 }
895 }
896
897 case filter<noun>::type::group:
898 {
899 bool truelogic = notlogic != f.get_notlogic();
900
901 std::list<std::string> clauses;
902 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
903 return recur(f2, truelogic);
904 });
905
906 if (truelogic == f.get_orlogic())
907 {
908 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
909 } else {
910 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
911 }
912 }
913 }
914 };
915
916 cond << recur(_hyponym_of, _hyponym_of.get_notlogic());
917 cond << ")";
918 conditions.push_back(cond.str());
919 }
920
921 if (_is_part_meronym)
922 {
923 conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)");
924 }
925
926 if (!_part_meronym_of.empty())
927 {
928 std::stringstream cond;
929 if (_part_meronym_of.get_notlogic())
930 {
931 cond << "noun_id NOT IN";
932 } else {
933 cond << "noun_id IN";
934 }
935
936 cond << "(SELECT meronym_id FROM part_meronymy WHERE ";
937
938 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
939 switch (f.get_type())
940 {
941 case filter<noun>::type::singleton:
942 {
943 bindings.emplace_back(f.get_elem()._id);
944
945 if (notlogic == f.get_notlogic())
946 {
947 return "holonym_id = ?";
948 } else {
949 return "holonym_id != ?";
950 }
951 }
952
953 case filter<noun>::type::group:
954 {
955 bool truelogic = notlogic != f.get_notlogic();
956
957 std::list<std::string> clauses;
958 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
959 return recur(f2, truelogic);
960 });
961
962 if (truelogic == f.get_orlogic())
963 {
964 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
965 } else {
966 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
967 }
968 }
969 }
970 };
971
972 cond << recur(_part_meronym_of, _part_meronym_of.get_notlogic());
973 cond << ")";
974 conditions.push_back(cond.str());
975 }
976
977 if (!_full_part_meronym_of.empty())
978 {
979 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
980 switch (f.get_type())
981 {
982 case filter<noun>::type::singleton:
983 {
984 if (notlogic == f.get_notlogic())
985 {
986 return "noun_id IN (SELECT meronym_id FROM part_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
987 } else {
988 return "noun_id NOT IN (SELECT meronym_id FROM part_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
989 }
990 }
991
992 case filter<noun>::type::group:
993 {
994 bool truelogic = notlogic != f.get_notlogic();
995
996 std::list<std::string> clauses;
997 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
998 return recur(f2, truelogic);
999 });
1000
1001 if (truelogic == f.get_orlogic())
1002 {
1003 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1004 } else {
1005 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1006 }
1007 }
1008 }
1009 };
1010
1011 conditions.push_back(recur(_full_part_meronym_of, false));
1012 }
1013
1014 if (_is_part_holonym)
1015 {
1016 conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)");
1017 }
1018
1019 if (!_part_holonym_of.empty())
1020 {
1021 std::stringstream cond;
1022 if (_part_holonym_of.get_notlogic())
1023 {
1024 cond << "noun_id NOT IN";
1025 } else {
1026 cond << "noun_id IN";
1027 }
1028
1029 cond << "(SELECT holonym_id FROM part_meronymy WHERE ";
1030
1031 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1032 switch (f.get_type())
1033 {
1034 case filter<noun>::type::singleton:
1035 {
1036 bindings.emplace_back(f.get_elem()._id);
1037
1038 if (notlogic == f.get_notlogic())
1039 {
1040 return "meronym_id = ?";
1041 } else {
1042 return "meronym_id != ?";
1043 }
1044 }
1045
1046 case filter<noun>::type::group:
1047 {
1048 bool truelogic = notlogic != f.get_notlogic();
1049
1050 std::list<std::string> clauses;
1051 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1052 return recur(f2, truelogic);
1053 });
1054
1055 if (truelogic == f.get_orlogic())
1056 {
1057 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1058 } else {
1059 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1060 }
1061 }
1062 }
1063 };
1064
1065 cond << recur(_part_holonym_of, _part_holonym_of.get_notlogic());
1066 cond << ")";
1067 conditions.push_back(cond.str());
1068 }
1069
1070 if (!_full_part_holonym_of.empty())
1071 {
1072 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1073 switch (f.get_type())
1074 {
1075 case filter<noun>::type::singleton:
1076 {
1077 if (notlogic == f.get_notlogic())
1078 {
1079 return "noun_id IN (SELECT holonym_id FROM part_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
1080 } else {
1081 return "noun_id NOT IN (SELECT holonym_id FROM part_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
1082 }
1083 }
1084
1085 case filter<noun>::type::group:
1086 {
1087 bool truelogic = notlogic != f.get_notlogic();
1088
1089 std::list<std::string> clauses;
1090 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1091 return recur(f2, truelogic);
1092 });
1093
1094 if (truelogic == f.get_orlogic())
1095 {
1096 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1097 } else {
1098 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1099 }
1100 }
1101 }
1102 };
1103
1104 conditions.push_back(recur(_full_part_holonym_of, false));
1105 }
1106
1107 if (_is_substance_meronym)
1108 {
1109 conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)");
1110 }
1111
1112 if (!_substance_meronym_of.empty())
1113 {
1114 std::stringstream cond;
1115 if (_substance_meronym_of.get_notlogic())
1116 {
1117 cond << "noun_id NOT IN";
1118 } else {
1119 cond << "noun_id IN";
1120 }
1121
1122 cond << "(SELECT meronym_id FROM substance_meronymy WHERE ";
1123
1124 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1125 switch (f.get_type())
1126 {
1127 case filter<noun>::type::singleton:
1128 {
1129 bindings.emplace_back(f.get_elem()._id);
1130
1131 if (notlogic == f.get_notlogic())
1132 {
1133 return "holonym_id = ?";
1134 } else {
1135 return "holonym_id != ?";
1136 }
1137 }
1138
1139 case filter<noun>::type::group:
1140 {
1141 bool truelogic = notlogic != f.get_notlogic();
1142
1143 std::list<std::string> clauses;
1144 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1145 return recur(f2, truelogic);
1146 });
1147
1148 if (truelogic == f.get_orlogic())
1149 {
1150 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1151 } else {
1152 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1153 }
1154 }
1155 }
1156 };
1157
1158 cond << recur(_substance_meronym_of, _substance_meronym_of.get_notlogic());
1159 cond << ")";
1160 conditions.push_back(cond.str());
1161 }
1162
1163 if (!_full_substance_meronym_of.empty())
1164 {
1165 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1166 switch (f.get_type())
1167 {
1168 case filter<noun>::type::singleton:
1169 {
1170 if (notlogic == f.get_notlogic())
1171 {
1172 return "noun_id IN (SELECT meronym_id FROM substance_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
1173 } else {
1174 return "noun_id NOT IN (SELECT meronym_id FROM substance_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
1175 }
1176 }
1177
1178 case filter<noun>::type::group:
1179 {
1180 bool truelogic = notlogic != f.get_notlogic();
1181
1182 std::list<std::string> clauses;
1183 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1184 return recur(f2, truelogic);
1185 });
1186
1187 if (truelogic == f.get_orlogic())
1188 {
1189 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1190 } else {
1191 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1192 }
1193 }
1194 }
1195 };
1196
1197 conditions.push_back(recur(_full_substance_meronym_of, false));
1198 }
1199
1200 if (_is_substance_holonym)
1201 {
1202 conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)");
1203 }
1204
1205 if (!_substance_holonym_of.empty())
1206 {
1207 std::stringstream cond;
1208 if (_substance_holonym_of.get_notlogic())
1209 {
1210 cond << "noun_id NOT IN";
1211 } else {
1212 cond << "noun_id IN";
1213 }
1214
1215 cond << "(SELECT holonym_id FROM substance_meronymy WHERE ";
1216
1217 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1218 switch (f.get_type())
1219 {
1220 case filter<noun>::type::singleton:
1221 {
1222 bindings.emplace_back(f.get_elem()._id);
1223
1224 if (notlogic == f.get_notlogic())
1225 {
1226 return "meronym_id = ?";
1227 } else {
1228 return "meronym_id != ?";
1229 }
1230 }
1231
1232 case filter<noun>::type::group:
1233 {
1234 bool truelogic = notlogic != f.get_notlogic();
1235
1236 std::list<std::string> clauses;
1237 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1238 return recur(f2, truelogic);
1239 });
1240
1241 if (truelogic == f.get_orlogic())
1242 {
1243 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1244 } else {
1245 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1246 }
1247 }
1248 }
1249 };
1250
1251 cond << recur(_substance_holonym_of, _substance_holonym_of.get_notlogic());
1252 cond << ")";
1253 conditions.push_back(cond.str());
1254 }
1255
1256 if (!_full_substance_holonym_of.empty())
1257 {
1258 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1259 switch (f.get_type())
1260 {
1261 case filter<noun>::type::singleton:
1262 {
1263 if (notlogic == f.get_notlogic())
1264 {
1265 return "noun_id IN (SELECT holonym_id FROM substance_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
1266 } else {
1267 return "noun_id NOT IN (SELECT holonym_id FROM substance_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
1268 }
1269 }
1270
1271 case filter<noun>::type::group:
1272 {
1273 bool truelogic = notlogic != f.get_notlogic();
1274
1275 std::list<std::string> clauses;
1276 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1277 return recur(f2, truelogic);
1278 });
1279
1280 if (truelogic == f.get_orlogic())
1281 {
1282 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1283 } else {
1284 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1285 }
1286 }
1287 }
1288 };
1289
1290 conditions.push_back(recur(_full_substance_holonym_of, false));
1291 }
1292
1293 if (_is_member_meronym)
1294 {
1295 conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)");
1296 }
1297
1298 if (!_member_meronym_of.empty())
1299 {
1300 std::stringstream cond;
1301 if (_member_meronym_of.get_notlogic())
1302 {
1303 cond << "noun_id NOT IN";
1304 } else {
1305 cond << "noun_id IN";
1306 }
1307
1308 cond << "(SELECT meronym_id FROM member_meronymy WHERE ";
1309
1310 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1311 switch (f.get_type())
1312 {
1313 case filter<noun>::type::singleton:
1314 {
1315 bindings.emplace_back(f.get_elem()._id);
1316
1317 if (notlogic == f.get_notlogic())
1318 {
1319 return "holonym_id = ?";
1320 } else {
1321 return "holonym_id != ?";
1322 }
1323 }
1324
1325 case filter<noun>::type::group:
1326 {
1327 bool truelogic = notlogic != f.get_notlogic();
1328
1329 std::list<std::string> clauses;
1330 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1331 return recur(f2, truelogic);
1332 });
1333
1334 if (truelogic == f.get_orlogic())
1335 {
1336 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1337 } else {
1338 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1339 }
1340 }
1341 }
1342 };
1343
1344 cond << recur(_member_meronym_of, _member_meronym_of.get_notlogic());
1345 cond << ")";
1346 conditions.push_back(cond.str());
1347 }
1348
1349 if (!_full_member_meronym_of.empty())
1350 {
1351 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1352 switch (f.get_type())
1353 {
1354 case filter<noun>::type::singleton:
1355 {
1356 if (notlogic == f.get_notlogic())
1357 {
1358 return "noun_id IN (SELECT meronym_id FROM member_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
1359 } else {
1360 return "noun_id NOT IN (SELECT meronym_id FROM member_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
1361 }
1362 }
1363
1364 case filter<noun>::type::group:
1365 {
1366 bool truelogic = notlogic != f.get_notlogic();
1367
1368 std::list<std::string> clauses;
1369 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1370 return recur(f2, truelogic);
1371 });
1372
1373 if (truelogic == f.get_orlogic())
1374 {
1375 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1376 } else {
1377 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1378 }
1379 }
1380 }
1381 };
1382
1383 conditions.push_back(recur(_full_member_meronym_of, false));
1384 }
1385
1386 if (_is_member_holonym)
1387 {
1388 conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)");
1389 }
1390
1391 if (!_member_holonym_of.empty())
1392 {
1393 std::stringstream cond;
1394 if (_member_holonym_of.get_notlogic())
1395 {
1396 cond << "noun_id NOT IN";
1397 } else {
1398 cond << "noun_id IN";
1399 }
1400
1401 cond << "(SELECT holonym_id FROM member_meronymy WHERE ";
1402
1403 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1404 switch (f.get_type())
1405 {
1406 case filter<noun>::type::singleton:
1407 {
1408 bindings.emplace_back(f.get_elem()._id);
1409
1410 if (notlogic == f.get_notlogic())
1411 {
1412 return "meronym_id = ?";
1413 } else {
1414 return "meronym_id != ?";
1415 }
1416 }
1417
1418 case filter<noun>::type::group:
1419 {
1420 bool truelogic = notlogic != f.get_notlogic();
1421
1422 std::list<std::string> clauses;
1423 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1424 return recur(f2, truelogic);
1425 });
1426
1427 if (truelogic == f.get_orlogic())
1428 {
1429 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1430 } else {
1431 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1432 }
1433 }
1434 }
1435 };
1436
1437 cond << recur(_member_holonym_of, _member_holonym_of.get_notlogic());
1438 cond << ")";
1439 conditions.push_back(cond.str());
1440 }
1441
1442 if (!_full_member_holonym_of.empty())
1443 {
1444 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1445 switch (f.get_type())
1446 {
1447 case filter<noun>::type::singleton:
1448 {
1449 if (notlogic == f.get_notlogic())
1450 {
1451 return "noun_id IN (SELECT holonym_id FROM member_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
1452 } else {
1453 return "noun_id NOT IN (SELECT holonym_id FROM member_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
1454 }
1455 }
1456
1457 case filter<noun>::type::group:
1458 {
1459 bool truelogic = notlogic != f.get_notlogic();
1460
1461 std::list<std::string> clauses;
1462 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1463 return recur(f2, truelogic);
1464 });
1465
1466 if (truelogic == f.get_orlogic())
1467 {
1468 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1469 } else {
1470 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1471 }
1472 }
1473 }
1474 };
1475
1476 conditions.push_back(recur(_full_member_holonym_of, false));
1477 }
1478
1479 if (_is_proper)
1480 {
1481 conditions.push_back("proper = 1");
1482 }
1483
1484 if (_is_not_proper)
1485 {
1486 conditions.push_back("proper = 0");
1487 }
1488
1489 if (_is_instance)
1490 {
1491 conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)");
1492 }
1493
1494 if (!_instance_of.empty())
1495 {
1496 std::stringstream cond;
1497 if (_instance_of.get_notlogic())
1498 {
1499 cond << "noun_id NOT IN";
1500 } else {
1501 cond << "noun_id IN";
1502 }
1503
1504 cond << "(SELECT instance_id FROM instantiation WHERE ";
1505
1506 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1507 switch (f.get_type())
1508 {
1509 case filter<noun>::type::singleton:
1510 {
1511 bindings.emplace_back(f.get_elem()._id);
1512
1513 if (notlogic == f.get_notlogic())
1514 {
1515 return "class_id = ?";
1516 } else {
1517 return "class_id != ?";
1518 }
1519 }
1520
1521 case filter<noun>::type::group:
1522 {
1523 bool truelogic = notlogic != f.get_notlogic();
1524
1525 std::list<std::string> clauses;
1526 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1527 return recur(f2, truelogic);
1528 });
1529
1530 if (truelogic == f.get_orlogic())
1531 {
1532 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1533 } else {
1534 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1535 }
1536 }
1537 }
1538 };
1539
1540 cond << recur(_instance_of, _instance_of.get_notlogic());
1541 cond << ")";
1542 conditions.push_back(cond.str());
1543 }
1544
1545 if (_is_class)
1546 {
1547 conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)");
1548 }
1549
1550 if (!_class_of.empty())
1551 {
1552 std::stringstream cond;
1553 if (_class_of.get_notlogic())
1554 {
1555 cond << "noun_id NOT IN";
1556 } else {
1557 cond << "noun_id IN";
1558 }
1559
1560 cond << "(SELECT class_id FROM instantiation WHERE ";
1561
1562 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1563 switch (f.get_type())
1564 {
1565 case filter<noun>::type::singleton:
1566 {
1567 bindings.emplace_back(f.get_elem()._id);
1568
1569 if (notlogic == f.get_notlogic())
1570 {
1571 return "instance_id = ?";
1572 } else {
1573 return "instance_id != ?";
1574 }
1575 }
1576
1577 case filter<noun>::type::group:
1578 {
1579 bool truelogic = notlogic != f.get_notlogic();
1580
1581 std::list<std::string> clauses;
1582 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1583 return recur(f2, truelogic);
1584 });
1585
1586 if (truelogic == f.get_orlogic())
1587 {
1588 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1589 } else {
1590 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1591 }
1592 }
1593 }
1594 };
1595
1596 cond << recur(_class_of, _class_of.get_notlogic());
1597 cond << ")";
1598 conditions.push_back(cond.str());
1599 }
1600
1601 if (_has_synonyms)
1602 {
1603 conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_synonymy)");
1604 }
1605
1606 if (!_synonym_of.empty())
1607 {
1608 std::stringstream cond;
1609 if (_synonym_of.get_notlogic())
1610 {
1611 cond << "noun_id NOT IN";
1612 } else {
1613 cond << "noun_id IN";
1614 }
1615
1616 cond << "(SELECT noun_2_id FROM noun_synonymy WHERE ";
1617
1618 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1619 switch (f.get_type())
1620 {
1621 case filter<noun>::type::singleton:
1622 {
1623 bindings.emplace_back(f.get_elem()._id);
1624
1625 if (notlogic == f.get_notlogic())
1626 {
1627 return "noun_1_id = ?";
1628 } else {
1629 return "noun_1_id != ?";
1630 }
1631 }
1632
1633 case filter<noun>::type::group:
1634 {
1635 bool truelogic = notlogic != f.get_notlogic();
1636
1637 std::list<std::string> clauses;
1638 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1639 return recur(f2, truelogic);
1640 });
1641
1642 if (truelogic == f.get_orlogic())
1643 {
1644 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1645 } else {
1646 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1647 }
1648 }
1649 }
1650 };
1651
1652 cond << recur(_synonym_of, _synonym_of.get_notlogic());
1653 cond << ")";
1654 conditions.push_back(cond.str());
1655 }
1656
1657 if (_has_antonyms)
1658 {
1659 conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_antonymy)");
1660 }
1661
1662 if (!_antonym_of.empty())
1663 {
1664 std::stringstream cond;
1665 if (_antonym_of.get_notlogic())
1666 {
1667 cond << "noun_id NOT IN";
1668 } else {
1669 cond << "noun_id IN";
1670 }
1671
1672 cond << "(SELECT noun_2_id FROM noun_antonymy WHERE ";
1673
1674 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
1675 switch (f.get_type())
1676 {
1677 case filter<noun>::type::singleton:
1678 {
1679 bindings.emplace_back(f.get_elem()._id);
1680
1681 if (notlogic == f.get_notlogic())
1682 {
1683 return "noun_1_id = ?";
1684 } else {
1685 return "noun_1_id != ?";
1686 }
1687 }
1688
1689 case filter<noun>::type::group:
1690 {
1691 bool truelogic = notlogic != f.get_notlogic();
1692
1693 std::list<std::string> clauses;
1694 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
1695 return recur(f2, truelogic);
1696 });
1697
1698 if (truelogic == f.get_orlogic())
1699 {
1700 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1701 } else {
1702 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1703 }
1704 }
1705 }
1706 };
1707
1708 cond << recur(_antonym_of, _antonym_of.get_notlogic());
1709 cond << ")";
1710 conditions.push_back(cond.str());
1711 }
1712
1713 if (_has_pertainym)
1714 {
1715 conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)");
1716 }
1717
1718 if (!_anti_pertainym_of.empty())
1719 {
1720 std::stringstream cond;
1721 if (_anti_pertainym_of.get_notlogic())
1722 {
1723 cond << "noun_id NOT IN";
1724 } else {
1725 cond << "noun_id IN";
1726 }
1727
1728 cond << "(SELECT noun_id FROM pertainymy WHERE ";
1729
1730 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
1731 switch (f.get_type())
1732 {
1733 case filter<adjective>::type::singleton:
1734 {
1735 bindings.emplace_back(f.get_elem()._id);
1736
1737 if (notlogic == f.get_notlogic())
1738 {
1739 return "pertainym_id = ?";
1740 } else {
1741 return "pertainym_id != ?";
1742 }
1743 }
1744
1745 case filter<adjective>::type::group:
1746 {
1747 bool truelogic = notlogic != f.get_notlogic();
1748
1749 std::list<std::string> clauses;
1750 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
1751 return recur(f2, truelogic);
1752 });
1753
1754 if (truelogic == f.get_orlogic())
1755 {
1756 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1757 } else {
1758 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1759 }
1760 }
1761 }
1762 };
1763
1764 cond << recur(_anti_pertainym_of, _anti_pertainym_of.get_notlogic());
1765 cond << ")";
1766 conditions.push_back(cond.str());
1767 }
1768
1769 if (_is_attribute)
1770 {
1771 conditions.push_back("noun_id IN (SELECT noun_id FROM variation)");
1772 }
1773
1774 if (!_attribute_of.empty())
1775 {
1776 std::stringstream cond;
1777 if (_attribute_of.get_notlogic())
1778 {
1779 cond << "noun_id NOT IN";
1780 } else {
1781 cond << "noun_id IN";
1782 }
1783
1784 cond << "(SELECT noun_id FROM variation WHERE ";
1785
1786 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
1787 switch (f.get_type())
1788 {
1789 case filter<adjective>::type::singleton:
1790 {
1791 bindings.emplace_back(f.get_elem()._id);
1792
1793 if (notlogic == f.get_notlogic())
1794 {
1795 return "adjective_id = ?";
1796 } else {
1797 return "adjective_id != ?";
1798 }
1799 }
1800
1801 case filter<adjective>::type::group:
1802 {
1803 bool truelogic = notlogic != f.get_notlogic();
1804
1805 std::list<std::string> clauses;
1806 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
1807 return recur(f2, truelogic);
1808 });
1809
1810 if (truelogic == f.get_orlogic())
1811 {
1812 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
1813 } else {
1814 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1815 }
1816 }
1817 }
1818 };
1819
1820 cond << recur(_attribute_of, _attribute_of.get_notlogic());
1821 cond << ")";
1822 conditions.push_back(cond.str());
1823 }
1824
1825 if (_at_least_n_images != unlimited)
1826 {
1827 conditions.push_back("images >= ?");
1828 bindings.emplace_back(_at_least_n_images);
1829 }
1830
1831 if (!_with_wnid.empty())
1832 {
1833 std::vector<std::string> clauses(_with_wnid.size(), "wnid = ?");
1834 std::string cond = verbly::implode(std::begin(clauses), std::end(clauses), " OR ");
1835 conditions.push_back("(" + cond + ")");
1836
1837 for (auto wnid : _with_wnid)
1838 {
1839 bindings.emplace_back(wnid);
1840 }
1841 }
1842
1843 /*
1844 if (!_derived_from_adjective.empty())
1845 {
1846 std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ");
1847 std::string cond = "noun_id IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1848 conditions.push_back(cond);
1849 }
1850
1851 if (!_not_derived_from_adjective.empty())
1852 {
1853 std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ");
1854 std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1855 conditions.push_back(cond);
1856 }
1857
1858 if (!_derived_from_adverb.empty())
1859 {
1860 std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV");
1861 std::string cond = "noun_id IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1862 conditions.push_back(cond);
1863 }
1864
1865 if (!_not_derived_from_adverb.empty())
1866 {
1867 std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV");
1868 std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1869 conditions.push_back(cond);
1870 }
1871
1872 if (!_derived_from_noun.empty())
1873 {
1874 std::list<std::string> clauses(_derived_from_noun.size(), "noun_2_id = @DERN");
1875 std::string cond = "noun_id IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1876 conditions.push_back(cond);
1877 }
1878
1879 if (!_not_derived_from_noun.empty())
1880 {
1881 std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_2_id = @NDERN");
1882 std::string cond = "noun_id NOT IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
1883 conditions.push_back(cond);
1884 }
1885 */
1886 if (!conditions.empty())
1887 {
1888 construct << " WHERE ";
1889 construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND ");
1890 }
1891
1892 if (_random)
1893 {
1894 construct << " ORDER BY RANDOM()";
1895 }
1896
1897 if (_limit != unlimited)
1898 {
1899 construct << " LIMIT " << _limit;
1900 }
1901
1902 sqlite3_stmt* ppstmt;
1903 std::string query = construct.str();
1904 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
1905 {
1906 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
1907 }
1908
1909 int i = 1;
1910 for (auto& binding : bindings)
1911 {
1912 switch (binding.get_type())
1913 {
1914 case binding::type::integer:
1915 {
1916 sqlite3_bind_int(ppstmt, i, binding.get_integer());
1917
1918 break;
1919 }
1920
1921 case binding::type::string:
1922 {
1923 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
1924
1925 break;
1926 }
1927 }
1928
1929 i++;
1930 }
1931
1932 /*
1933 for (auto adj : _derived_from_adjective)
1934 {
1935 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id);
1936 }
1937
1938 for (auto adj : _not_derived_from_adjective)
1939 {
1940 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id);
1941 }
1942
1943 for (auto adv : _derived_from_adverb)
1944 {
1945 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id);
1946 }
1947
1948 for (auto adv : _not_derived_from_adverb)
1949 {
1950 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id);
1951 }
1952
1953 for (auto n : _derived_from_noun)
1954 {
1955 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id);
1956 }
1957
1958 for (auto n : _not_derived_from_noun)
1959 {
1960 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id);
1961 }
1962*/
1963 std::list<noun> output;
1964 while (sqlite3_step(ppstmt) == SQLITE_ROW)
1965 {
1966 noun tnc {_data, sqlite3_column_int(ppstmt, 0)};
1967 tnc._singular = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
1968
1969 if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL)
1970 {
1971 tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
1972 }
1973
1974 tnc._wnid = sqlite3_column_int(ppstmt, 3);
1975
1976 output.push_back(tnc);
1977 }
1978
1979 sqlite3_finalize(ppstmt);
1980
1981 for (auto& noun : output)
1982 {
1983 query = "SELECT pronunciation, prerhyme, rhyme FROM noun_pronunciations WHERE noun_id = ?";
1984 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
1985 {
1986 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
1987 }
1988
1989 sqlite3_bind_int(ppstmt, 1, noun._id);
1990
1991 while (sqlite3_step(ppstmt) == SQLITE_ROW)
1992 {
1993 std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0)));
1994 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
1995
1996 noun.pronunciations.push_back(phonemes);
1997
1998 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
1999 {
2000 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
2001 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
2002
2003 noun.rhymes.emplace_back(prerhyme, rhyming);
2004 }
2005 }
2006
2007 sqlite3_finalize(ppstmt);
2008 }
2009
2010 return output;
2011 }
2012
2013};