diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-04-15 17:24:44 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-04-15 17:24:44 -0400 |
commit | 040ee58fecdc9c478004bc2e554e1ae126ec4602 (patch) | |
tree | 672a75690952ba8055ab9765ba0a475e056e35d4 | |
parent | 3a225f5eb709262b9d44d49519136ea9a2a71000 (diff) | |
download | verbly-040ee58fecdc9c478004bc2e554e1ae126ec4602.tar.gz verbly-040ee58fecdc9c478004bc2e554e1ae126ec4602.tar.bz2 verbly-040ee58fecdc9c478004bc2e554e1ae126ec4602.zip |
Added support for ImageNet and fixed bug with query interface
Datafile change: nouns now know how many images are associated with them on ImageNet, and also have their WordNet synset ID saved so that you can query for images of that noun via the ImageNet API. So far, verbly only exposes the ImageNet API URL, and doesn't actually interact with it itself. This may be changed in the future. The query interface had a huge issue in which multiple instances of the same condition would overwrite each other. This has been fixed.
-rw-r--r-- | generator/generator.cpp | 57 | ||||
-rw-r--r-- | generator/schema.sql | 4 | ||||
-rw-r--r-- | lib/adjective_query.cpp | 147 | ||||
-rw-r--r-- | lib/adverb_query.cpp | 103 | ||||
-rw-r--r-- | lib/data.cpp | 117 | ||||
-rw-r--r-- | lib/data.h | 32 | ||||
-rw-r--r-- | lib/frame_query.cpp | 30 | ||||
-rw-r--r-- | lib/noun.cpp | 17 | ||||
-rw-r--r-- | lib/noun.h | 4 | ||||
-rw-r--r-- | lib/noun_query.cpp | 274 | ||||
-rw-r--r-- | lib/noun_query.h | 6 | ||||
-rw-r--r-- | lib/preposition.cpp | 30 | ||||
-rw-r--r-- | lib/verb_query.cpp | 39 |
13 files changed, 551 insertions, 309 deletions
diff --git a/generator/generator.cpp b/generator/generator.cpp index 6fbbfb8..e67bda7 100644 --- a/generator/generator.cpp +++ b/generator/generator.cpp | |||
@@ -81,6 +81,7 @@ std::map<std::string, verb_t> verbs; | |||
81 | std::map<std::string, adjective_t> adjectives; | 81 | std::map<std::string, adjective_t> adjectives; |
82 | std::map<std::string, noun_t> nouns; | 82 | std::map<std::string, noun_t> nouns; |
83 | std::map<int, std::map<int, int>> wn; | 83 | std::map<int, std::map<int, int>> wn; |
84 | std::map<int, int> images; | ||
84 | std::map<std::string, std::set<std::string>> pronunciations; | 85 | std::map<std::string, std::set<std::string>> pronunciations; |
85 | 86 | ||
86 | void print_usage() | 87 | void print_usage() |
@@ -89,10 +90,10 @@ void print_usage() | |||
89 | std::cout << "-------------------------" << std::endl; | 90 | std::cout << "-------------------------" << std::endl; |
90 | std::cout << "Requires exactly six arguments." << std::endl; | 91 | std::cout << "Requires exactly six arguments." << std::endl; |
91 | std::cout << "1. The path to a VerbNet data directory." << std::endl; | 92 | std::cout << "1. The path to a VerbNet data directory." << std::endl; |
92 | std::cout << "2. The path to a SemLink vnpbMappings file." << std::endl; | 93 | std::cout << "2. The path to an AGID infl.txt file." << std::endl; |
93 | std::cout << "3. The path to an AGID infl.txt file." << std::endl; | 94 | std::cout << "3. The path to a WordNet prolog data directory." << std::endl; |
94 | std::cout << "4. The path to a WordNet prolog data directory." << std::endl; | 95 | std::cout << "4. The path to a CMUDICT pronunciation file." << std::endl; |
95 | std::cout << "5. The path to a CMUDICT pronunciation file." << std::endl; | 96 | std::cout << "5. The path to an ImageNet urls.txt file." << std::endl; |
96 | std::cout << "6. Datafile output path." << std::endl; | 97 | std::cout << "6. Datafile output path." << std::endl; |
97 | 98 | ||
98 | exit(1); | 99 | exit(1); |
@@ -431,10 +432,10 @@ int main(int argc, char** argv) | |||
431 | // Get verbs from AGID | 432 | // Get verbs from AGID |
432 | std::cout << "Reading inflections..." << std::endl; | 433 | std::cout << "Reading inflections..." << std::endl; |
433 | 434 | ||
434 | std::ifstream agidfile(argv[3]); | 435 | std::ifstream agidfile(argv[2]); |
435 | if (!agidfile.is_open()) | 436 | if (!agidfile.is_open()) |
436 | { | 437 | { |
437 | std::cout << "Could not open AGID file: " << argv[3] << std::endl; | 438 | std::cout << "Could not open AGID file: " << argv[2] << std::endl; |
438 | print_usage(); | 439 | print_usage(); |
439 | } | 440 | } |
440 | 441 | ||
@@ -562,10 +563,10 @@ int main(int argc, char** argv) | |||
562 | // Pronounciations | 563 | // Pronounciations |
563 | std::cout << "Reading pronunciations..." << std::endl; | 564 | std::cout << "Reading pronunciations..." << std::endl; |
564 | 565 | ||
565 | std::ifstream pronfile(argv[5]); | 566 | std::ifstream pronfile(argv[4]); |
566 | if (!pronfile.is_open()) | 567 | if (!pronfile.is_open()) |
567 | { | 568 | { |
568 | std::cout << "Could not open CMUDICT file: " << argv[5] << std::endl; | 569 | std::cout << "Could not open CMUDICT file: " << argv[4] << std::endl; |
569 | print_usage(); | 570 | print_usage(); |
570 | } | 571 | } |
571 | 572 | ||
@@ -593,6 +594,36 @@ int main(int argc, char** argv) | |||
593 | } | 594 | } |
594 | } | 595 | } |
595 | 596 | ||
597 | // Images | ||
598 | std::cout << "Reading images..." << std::endl; | ||
599 | |||
600 | std::ifstream imagefile(argv[5]); | ||
601 | if (!imagefile.is_open()) | ||
602 | { | ||
603 | std::cout << "Could not open ImageNet file: " << argv[5] << std::endl; | ||
604 | print_usage(); | ||
605 | } | ||
606 | |||
607 | for (;;) | ||
608 | { | ||
609 | std::string line; | ||
610 | if (!getline(imagefile, line)) | ||
611 | { | ||
612 | break; | ||
613 | } | ||
614 | |||
615 | if (line.back() == '\r') | ||
616 | { | ||
617 | line.pop_back(); | ||
618 | } | ||
619 | |||
620 | std::string wnid_s = line.substr(1, 8); | ||
621 | int wnid = stoi(wnid_s) + 100000000; | ||
622 | images[wnid]++; | ||
623 | } | ||
624 | |||
625 | imagefile.close(); | ||
626 | |||
596 | // Start writing output | 627 | // Start writing output |
597 | std::cout << "Writing schema..." << std::endl; | 628 | std::cout << "Writing schema..." << std::endl; |
598 | 629 | ||
@@ -972,7 +1003,7 @@ int main(int argc, char** argv) | |||
972 | // - sa: specification (e.g. inaccurate (general) can mean imprecise or incorrect (specific)) | 1003 | // - sa: specification (e.g. inaccurate (general) can mean imprecise or incorrect (specific)) |
973 | // - sim: synonymy (e.g. cheerful/happy, happy/cheerful) | 1004 | // - sim: synonymy (e.g. cheerful/happy, happy/cheerful) |
974 | // - syntax: positioning flags for some adjectives | 1005 | // - syntax: positioning flags for some adjectives |
975 | std::string wnpref {argv[4]}; | 1006 | std::string wnpref {argv[3]}; |
976 | if (wnpref.back() != '/') | 1007 | if (wnpref.back() != '/') |
977 | { | 1008 | { |
978 | wnpref += '/'; | 1009 | wnpref += '/'; |
@@ -1027,9 +1058,9 @@ int main(int argc, char** argv) | |||
1027 | { | 1058 | { |
1028 | if (nouns.count(word) == 1) | 1059 | if (nouns.count(word) == 1) |
1029 | { | 1060 | { |
1030 | query = "INSERT INTO nouns (singular, proper, complexity, plural) VALUES (?, ?, ?, ?)"; | 1061 | query = "INSERT INTO nouns (singular, proper, complexity, images, wnid, plural) VALUES (?, ?, ?, ?, ?, ?)"; |
1031 | } else { | 1062 | } else { |
1032 | query = "INSERT INTO nouns (singular, proper, complexity) VALUES (?, ?, ?)"; | 1063 | query = "INSERT INTO nouns (singular, proper, complexity, images, wnid) VALUES (?, ?, ?, ?, ?)"; |
1033 | } | 1064 | } |
1034 | 1065 | ||
1035 | break; | 1066 | break; |
@@ -1083,10 +1114,12 @@ int main(int argc, char** argv) | |||
1083 | }) ? 1 : 0)); | 1114 | }) ? 1 : 0)); |
1084 | 1115 | ||
1085 | sqlite3_bind_int(ppstmt, 3, verbly::split<std::list<std::string>>(word, " ").size()); | 1116 | sqlite3_bind_int(ppstmt, 3, verbly::split<std::list<std::string>>(word, " ").size()); |
1117 | sqlite3_bind_int(ppstmt, 4, images[synset_id]); | ||
1118 | sqlite3_bind_int(ppstmt, 5, synset_id); | ||
1086 | 1119 | ||
1087 | if (nouns.count(word) == 1) | 1120 | if (nouns.count(word) == 1) |
1088 | { | 1121 | { |
1089 | sqlite3_bind_text(ppstmt, 4, nouns[word].plural.c_str(), nouns[word].plural.length(), SQLITE_STATIC); | 1122 | sqlite3_bind_text(ppstmt, 6, nouns[word].plural.c_str(), nouns[word].plural.length(), SQLITE_STATIC); |
1090 | } | 1123 | } |
1091 | 1124 | ||
1092 | break; | 1125 | break; |
diff --git a/generator/schema.sql b/generator/schema.sql index f2445f0..9a39944 100644 --- a/generator/schema.sql +++ b/generator/schema.sql | |||
@@ -55,7 +55,9 @@ CREATE TABLE `nouns` ( | |||
55 | `singular` VARCHAR(32) NOT NULL, | 55 | `singular` VARCHAR(32) NOT NULL, |
56 | `plural` VARCHAR(32), | 56 | `plural` VARCHAR(32), |
57 | `proper` INTEGER(1) NOT NULL, | 57 | `proper` INTEGER(1) NOT NULL, |
58 | `complexity` INTEGER NOT NULL | 58 | `complexity` INTEGER NOT NULL, |
59 | `images` INTEGER NOT NULL, | ||
60 | `wnid` INTEGER NOT NULL | ||
59 | ); | 61 | ); |
60 | 62 | ||
61 | DROP TABLE IF EXISTS `hypernymy`; | 63 | DROP TABLE IF EXISTS `hypernymy`; |
diff --git a/lib/adjective_query.cpp b/lib/adjective_query.cpp index 283fdca..a7f915c 100644 --- a/lib/adjective_query.cpp +++ b/lib/adjective_query.cpp | |||
@@ -218,6 +218,7 @@ namespace verbly { | |||
218 | std::stringstream construct; | 218 | std::stringstream construct; |
219 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; | 219 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; |
220 | std::list<std::string> conditions; | 220 | std::list<std::string> conditions; |
221 | std::list<binding> bindings; | ||
221 | 222 | ||
222 | if (_has_prn) | 223 | if (_has_prn) |
223 | { | 224 | { |
@@ -226,14 +227,20 @@ namespace verbly { | |||
226 | 227 | ||
227 | if (!_rhymes.empty()) | 228 | if (!_rhymes.empty()) |
228 | { | 229 | { |
229 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | 230 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); |
230 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | 231 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; |
231 | conditions.push_back(cond); | 232 | conditions.push_back(cond); |
233 | |||
234 | for (auto rhyme : _rhymes) | ||
235 | { | ||
236 | bindings.emplace_back("%" + rhyme); | ||
237 | } | ||
232 | } | 238 | } |
233 | 239 | ||
234 | for (auto except : _except) | 240 | for (auto except : _except) |
235 | { | 241 | { |
236 | conditions.push_back("adjective_id != @EXCID"); | 242 | conditions.push_back("adjective_id != ?"); |
243 | bindings.emplace_back(except._id); | ||
237 | } | 244 | } |
238 | 245 | ||
239 | if (_requires_comparative_form) | 246 | if (_requires_comparative_form) |
@@ -261,11 +268,13 @@ namespace verbly { | |||
261 | { | 268 | { |
262 | case filter<std::string>::type::singleton: | 269 | case filter<std::string>::type::singleton: |
263 | { | 270 | { |
271 | bindings.emplace_back(f.get_elem() + "%"); | ||
272 | |||
264 | if (notlogic == f.get_notlogic()) | 273 | if (notlogic == f.get_notlogic()) |
265 | { | 274 | { |
266 | return "base_form LIKE @PREFIX"; | 275 | return "base_form LIKE ?"; |
267 | } else { | 276 | } else { |
268 | return "base_form NOT LIKE @PREFIX"; | 277 | return "base_form NOT LIKE ?"; |
269 | } | 278 | } |
270 | } | 279 | } |
271 | 280 | ||
@@ -298,11 +307,13 @@ namespace verbly { | |||
298 | { | 307 | { |
299 | case filter<std::string>::type::singleton: | 308 | case filter<std::string>::type::singleton: |
300 | { | 309 | { |
310 | bindings.emplace_back("%" + f.get_elem()); | ||
311 | |||
301 | if (notlogic == f.get_notlogic()) | 312 | if (notlogic == f.get_notlogic()) |
302 | { | 313 | { |
303 | return "base_form LIKE @SUFFIX"; | 314 | return "base_form LIKE ?"; |
304 | } else { | 315 | } else { |
305 | return "base_form NOT LIKE @SUFFIX"; | 316 | return "base_form NOT LIKE ?"; |
306 | } | 317 | } |
307 | } | 318 | } |
308 | 319 | ||
@@ -330,7 +341,8 @@ namespace verbly { | |||
330 | 341 | ||
331 | if (_with_complexity != unlimited) | 342 | if (_with_complexity != unlimited) |
332 | { | 343 | { |
333 | conditions.push_back("complexity = @COMPLEX"); | 344 | conditions.push_back("complexity = ?"); |
345 | bindings.emplace_back(_with_complexity); | ||
334 | } | 346 | } |
335 | 347 | ||
336 | if (_is_variant) | 348 | if (_is_variant) |
@@ -355,11 +367,13 @@ namespace verbly { | |||
355 | { | 367 | { |
356 | case filter<noun>::type::singleton: | 368 | case filter<noun>::type::singleton: |
357 | { | 369 | { |
370 | bindings.emplace_back(f.get_elem()._id); | ||
371 | |||
358 | if (notlogic == f.get_notlogic()) | 372 | if (notlogic == f.get_notlogic()) |
359 | { | 373 | { |
360 | return "noun_id = @ATTRID"; | 374 | return "noun_id = ?"; |
361 | } else { | 375 | } else { |
362 | return "noun_id != @ATTRID"; | 376 | return "noun_id != ?"; |
363 | } | 377 | } |
364 | } | 378 | } |
365 | 379 | ||
@@ -409,11 +423,13 @@ namespace verbly { | |||
409 | { | 423 | { |
410 | case filter<adjective>::type::singleton: | 424 | case filter<adjective>::type::singleton: |
411 | { | 425 | { |
426 | bindings.emplace_back(f.get_elem()._id); | ||
427 | |||
412 | if (notlogic == f.get_notlogic()) | 428 | if (notlogic == f.get_notlogic()) |
413 | { | 429 | { |
414 | return "adjective_1_id = @ANTID"; | 430 | return "adjective_1_id = ?"; |
415 | } else { | 431 | } else { |
416 | return "adjective_1_id != @ANTID"; | 432 | return "adjective_1_id != ?"; |
417 | } | 433 | } |
418 | } | 434 | } |
419 | 435 | ||
@@ -463,11 +479,13 @@ namespace verbly { | |||
463 | { | 479 | { |
464 | case filter<adjective>::type::singleton: | 480 | case filter<adjective>::type::singleton: |
465 | { | 481 | { |
482 | bindings.emplace_back(f.get_elem()._id); | ||
483 | |||
466 | if (notlogic == f.get_notlogic()) | 484 | if (notlogic == f.get_notlogic()) |
467 | { | 485 | { |
468 | return "adjective_1_id = @SYNID"; | 486 | return "adjective_1_id = ?"; |
469 | } else { | 487 | } else { |
470 | return "adjective_1_id != @SYNID"; | 488 | return "adjective_1_id != ?"; |
471 | } | 489 | } |
472 | } | 490 | } |
473 | 491 | ||
@@ -517,11 +535,13 @@ namespace verbly { | |||
517 | { | 535 | { |
518 | case filter<adjective>::type::singleton: | 536 | case filter<adjective>::type::singleton: |
519 | { | 537 | { |
538 | bindings.emplace_back(f.get_elem()._id); | ||
539 | |||
520 | if (notlogic == f.get_notlogic()) | 540 | if (notlogic == f.get_notlogic()) |
521 | { | 541 | { |
522 | return "specific_id = @SPECID"; | 542 | return "specific_id = ?"; |
523 | } else { | 543 | } else { |
524 | return "specific_id != @SPECID"; | 544 | return "specific_id != ?"; |
525 | } | 545 | } |
526 | } | 546 | } |
527 | 547 | ||
@@ -571,11 +591,13 @@ namespace verbly { | |||
571 | { | 591 | { |
572 | case filter<adjective>::type::singleton: | 592 | case filter<adjective>::type::singleton: |
573 | { | 593 | { |
594 | bindings.emplace_back(f.get_elem()._id); | ||
595 | |||
574 | if (notlogic == f.get_notlogic()) | 596 | if (notlogic == f.get_notlogic()) |
575 | { | 597 | { |
576 | return "general_id = @GENID"; | 598 | return "general_id = ?"; |
577 | } else { | 599 | } else { |
578 | return "general_id != @GENID"; | 600 | return "general_id != ?"; |
579 | } | 601 | } |
580 | } | 602 | } |
581 | 603 | ||
@@ -625,11 +647,13 @@ namespace verbly { | |||
625 | { | 647 | { |
626 | case filter<noun>::type::singleton: | 648 | case filter<noun>::type::singleton: |
627 | { | 649 | { |
650 | bindings.emplace_back(f.get_elem()._id); | ||
651 | |||
628 | if (notlogic == f.get_notlogic()) | 652 | if (notlogic == f.get_notlogic()) |
629 | { | 653 | { |
630 | return "noun_id = @APERID"; | 654 | return "noun_id = ?"; |
631 | } else { | 655 | } else { |
632 | return "noun_id != @APERID"; | 656 | return "noun_id != ?"; |
633 | } | 657 | } |
634 | } | 658 | } |
635 | 659 | ||
@@ -679,11 +703,13 @@ namespace verbly { | |||
679 | { | 703 | { |
680 | case filter<adverb>::type::singleton: | 704 | case filter<adverb>::type::singleton: |
681 | { | 705 | { |
706 | bindings.emplace_back(f.get_elem()._id); | ||
707 | |||
682 | if (notlogic == f.get_notlogic()) | 708 | if (notlogic == f.get_notlogic()) |
683 | { | 709 | { |
684 | return "mannernym_id = @MANID"; | 710 | return "mannernym_id = ?"; |
685 | } else { | 711 | } else { |
686 | return "mannernym_id != @MANID"; | 712 | return "mannernym_id != ?"; |
687 | } | 713 | } |
688 | } | 714 | } |
689 | 715 | ||
@@ -776,74 +802,29 @@ namespace verbly { | |||
776 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | 802 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); |
777 | } | 803 | } |
778 | 804 | ||
779 | if (!_rhymes.empty()) | 805 | int i = 1; |
806 | for (auto& binding : bindings) | ||
780 | { | 807 | { |
781 | int i = 0; | 808 | switch (binding.get_type()) |
782 | for (auto rhyme : _rhymes) | ||
783 | { | 809 | { |
784 | std::string rhymer = "%" + rhyme; | 810 | case binding::type::integer: |
785 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | 811 | { |
812 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
813 | |||
814 | break; | ||
815 | } | ||
786 | 816 | ||
787 | i++; | 817 | case binding::type::string: |
818 | { | ||
819 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); | ||
820 | |||
821 | break; | ||
822 | } | ||
788 | } | 823 | } |
824 | |||
825 | i++; | ||
789 | } | 826 | } |
790 | 827 | ||
791 | for (auto except : _except) | ||
792 | { | ||
793 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
794 | } | ||
795 | |||
796 | for (auto prefix : _with_prefix.inorder_flatten()) | ||
797 | { | ||
798 | std::string pfat = prefix + "%"; | ||
799 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PREFIX"), pfat.c_str(), pfat.length(), SQLITE_STATIC); | ||
800 | } | ||
801 | |||
802 | for (auto suffix : _with_suffix.inorder_flatten()) | ||
803 | { | ||
804 | std::string pfat = "%" + suffix; | ||
805 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SUFFIX"), pfat.c_str(), pfat.length(), SQLITE_STATIC); | ||
806 | } | ||
807 | |||
808 | if (_with_complexity != unlimited) | ||
809 | { | ||
810 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@COMPLEX"), _with_complexity); | ||
811 | } | ||
812 | |||
813 | for (auto attribute : _variant_of.inorder_flatten()) | ||
814 | { | ||
815 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); | ||
816 | } | ||
817 | |||
818 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
819 | { | ||
820 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
821 | } | ||
822 | |||
823 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
824 | { | ||
825 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
826 | } | ||
827 | |||
828 | for (auto specific : _generalization_of.inorder_flatten()) | ||
829 | { | ||
830 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); | ||
831 | } | ||
832 | |||
833 | for (auto general : _specification_of.inorder_flatten()) | ||
834 | { | ||
835 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); | ||
836 | } | ||
837 | |||
838 | for (auto n : _pertainym_of.inorder_flatten()) | ||
839 | { | ||
840 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); | ||
841 | } | ||
842 | |||
843 | for (auto mannernym : _anti_mannernym_of.inorder_flatten()) | ||
844 | { | ||
845 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); | ||
846 | } | ||
847 | /* | 828 | /* |
848 | for (auto adj : _derived_from_adjective) | 829 | for (auto adj : _derived_from_adjective) |
849 | { | 830 | { |
diff --git a/lib/adverb_query.cpp b/lib/adverb_query.cpp index c9d0d09..30ba92b 100644 --- a/lib/adverb_query.cpp +++ b/lib/adverb_query.cpp | |||
@@ -172,6 +172,7 @@ namespace verbly { | |||
172 | std::stringstream construct; | 172 | std::stringstream construct; |
173 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; | 173 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; |
174 | std::list<std::string> conditions; | 174 | std::list<std::string> conditions; |
175 | std::list<binding> bindings; | ||
175 | 176 | ||
176 | if (_has_prn) | 177 | if (_has_prn) |
177 | { | 178 | { |
@@ -180,14 +181,20 @@ namespace verbly { | |||
180 | 181 | ||
181 | if (!_rhymes.empty()) | 182 | if (!_rhymes.empty()) |
182 | { | 183 | { |
183 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | 184 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); |
184 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | 185 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; |
185 | conditions.push_back(cond); | 186 | conditions.push_back(cond); |
187 | |||
188 | for (auto rhyme : _rhymes) | ||
189 | { | ||
190 | bindings.emplace_back("%" + rhyme); | ||
191 | } | ||
186 | } | 192 | } |
187 | 193 | ||
188 | for (auto except : _except) | 194 | for (auto except : _except) |
189 | { | 195 | { |
190 | conditions.push_back("adverb_id != @EXCID"); | 196 | conditions.push_back("adverb_id != ?"); |
197 | bindings.emplace_back(except._id); | ||
191 | } | 198 | } |
192 | 199 | ||
193 | if (_requires_comparative_form) | 200 | if (_requires_comparative_form) |
@@ -207,11 +214,13 @@ namespace verbly { | |||
207 | { | 214 | { |
208 | case filter<std::string>::type::singleton: | 215 | case filter<std::string>::type::singleton: |
209 | { | 216 | { |
217 | bindings.emplace_back(f.get_elem() + "%"); | ||
218 | |||
210 | if (notlogic == f.get_notlogic()) | 219 | if (notlogic == f.get_notlogic()) |
211 | { | 220 | { |
212 | return "base_form LIKE @PREFIX"; | 221 | return "base_form LIKE ?"; |
213 | } else { | 222 | } else { |
214 | return "base_form NOT LIKE @PREFIX"; | 223 | return "base_form NOT LIKE ?"; |
215 | } | 224 | } |
216 | } | 225 | } |
217 | 226 | ||
@@ -244,11 +253,13 @@ namespace verbly { | |||
244 | { | 253 | { |
245 | case filter<std::string>::type::singleton: | 254 | case filter<std::string>::type::singleton: |
246 | { | 255 | { |
256 | bindings.emplace_back("%" + f.get_elem()); | ||
257 | |||
247 | if (notlogic == f.get_notlogic()) | 258 | if (notlogic == f.get_notlogic()) |
248 | { | 259 | { |
249 | return "base_form LIKE @SUFFIX"; | 260 | return "base_form LIKE ?"; |
250 | } else { | 261 | } else { |
251 | return "base_form NOT LIKE @SUFFIX"; | 262 | return "base_form NOT LIKE ?"; |
252 | } | 263 | } |
253 | } | 264 | } |
254 | 265 | ||
@@ -276,7 +287,8 @@ namespace verbly { | |||
276 | 287 | ||
277 | if (_with_complexity != unlimited) | 288 | if (_with_complexity != unlimited) |
278 | { | 289 | { |
279 | conditions.push_back("complexity = @COMPLEX"); | 290 | conditions.push_back("complexity = ?"); |
291 | bindings.emplace_back(_with_complexity); | ||
280 | } | 292 | } |
281 | 293 | ||
282 | if (_has_antonyms) | 294 | if (_has_antonyms) |
@@ -301,11 +313,13 @@ namespace verbly { | |||
301 | { | 313 | { |
302 | case filter<adverb>::type::singleton: | 314 | case filter<adverb>::type::singleton: |
303 | { | 315 | { |
316 | bindings.emplace_back(f.get_elem()._id); | ||
317 | |||
304 | if (notlogic == f.get_notlogic()) | 318 | if (notlogic == f.get_notlogic()) |
305 | { | 319 | { |
306 | return "adverb_1_id = @ANTID"; | 320 | return "adverb_1_id = ?"; |
307 | } else { | 321 | } else { |
308 | return "adverb_1_id != @ANTID"; | 322 | return "adverb_1_id != ?"; |
309 | } | 323 | } |
310 | } | 324 | } |
311 | 325 | ||
@@ -355,11 +369,13 @@ namespace verbly { | |||
355 | { | 369 | { |
356 | case filter<adverb>::type::singleton: | 370 | case filter<adverb>::type::singleton: |
357 | { | 371 | { |
372 | bindings.emplace_back(f.get_elem()._id); | ||
373 | |||
358 | if (notlogic == f.get_notlogic()) | 374 | if (notlogic == f.get_notlogic()) |
359 | { | 375 | { |
360 | return "adverb_1_id = @SYNID"; | 376 | return "adverb_1_id = ?"; |
361 | } else { | 377 | } else { |
362 | return "adverb_1_id != @SYNID"; | 378 | return "adverb_1_id != ?"; |
363 | } | 379 | } |
364 | } | 380 | } |
365 | 381 | ||
@@ -409,11 +425,13 @@ namespace verbly { | |||
409 | { | 425 | { |
410 | case filter<adjective>::type::singleton: | 426 | case filter<adjective>::type::singleton: |
411 | { | 427 | { |
428 | bindings.emplace_back(f.get_elem()._id); | ||
429 | |||
412 | if (notlogic == f.get_notlogic()) | 430 | if (notlogic == f.get_notlogic()) |
413 | { | 431 | { |
414 | return "adjective_id = @AMANID"; | 432 | return "adjective_id = ?"; |
415 | } else { | 433 | } else { |
416 | return "adjective_id != @AMANID"; | 434 | return "adjective_id != ?"; |
417 | } | 435 | } |
418 | } | 436 | } |
419 | 437 | ||
@@ -506,54 +524,29 @@ namespace verbly { | |||
506 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | 524 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); |
507 | } | 525 | } |
508 | 526 | ||
509 | if (!_rhymes.empty()) | 527 | int i = 1; |
528 | for (auto& binding : bindings) | ||
510 | { | 529 | { |
511 | int i = 0; | 530 | switch (binding.get_type()) |
512 | for (auto rhyme : _rhymes) | ||
513 | { | 531 | { |
514 | std::string rhymer = "%" + rhyme; | 532 | case binding::type::integer: |
515 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | 533 | { |
534 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
535 | |||
536 | break; | ||
537 | } | ||
516 | 538 | ||
517 | i++; | 539 | case binding::type::string: |
540 | { | ||
541 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); | ||
542 | |||
543 | break; | ||
544 | } | ||
518 | } | 545 | } |
546 | |||
547 | i++; | ||
519 | } | 548 | } |
520 | 549 | ||
521 | for (auto except : _except) | ||
522 | { | ||
523 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
524 | } | ||
525 | |||
526 | for (auto prefix : _with_prefix.inorder_flatten()) | ||
527 | { | ||
528 | std::string pfat = prefix + "%"; | ||
529 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PREFIX"), pfat.c_str(), pfat.length(), SQLITE_STATIC); | ||
530 | } | ||
531 | |||
532 | for (auto suffix : _with_suffix.inorder_flatten()) | ||
533 | { | ||
534 | std::string pfat = "%" + suffix; | ||
535 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SUFFIX"), pfat.c_str(), pfat.length(), SQLITE_STATIC); | ||
536 | } | ||
537 | |||
538 | if (_with_complexity != unlimited) | ||
539 | { | ||
540 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@COMPLEX"), _with_complexity); | ||
541 | } | ||
542 | |||
543 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
544 | { | ||
545 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
546 | } | ||
547 | |||
548 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
549 | { | ||
550 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
551 | } | ||
552 | |||
553 | for (auto adj : _mannernym_of.inorder_flatten()) | ||
554 | { | ||
555 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); | ||
556 | } | ||
557 | /* | 550 | /* |
558 | for (auto adj : _derived_from_adjective) | 551 | for (auto adj : _derived_from_adjective) |
559 | { | 552 | { |
diff --git a/lib/data.cpp b/lib/data.cpp index 5a9397b..c14956f 100644 --- a/lib/data.cpp +++ b/lib/data.cpp | |||
@@ -57,4 +57,121 @@ namespace verbly { | |||
57 | return preposition_query(*this); | 57 | return preposition_query(*this); |
58 | } | 58 | } |
59 | 59 | ||
60 | binding::type binding::get_type() const | ||
61 | { | ||
62 | return _type; | ||
63 | } | ||
64 | |||
65 | binding::binding(const binding& other) | ||
66 | { | ||
67 | _type = other._type; | ||
68 | |||
69 | switch (_type) | ||
70 | { | ||
71 | case type::integer: | ||
72 | { | ||
73 | _integer = other._integer; | ||
74 | |||
75 | break; | ||
76 | } | ||
77 | |||
78 | case type::string: | ||
79 | { | ||
80 | new(&_string) std::string(other._string); | ||
81 | |||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | binding::~binding() | ||
88 | { | ||
89 | switch (_type) | ||
90 | { | ||
91 | case type::string: | ||
92 | { | ||
93 | using string_type = std::string; | ||
94 | _string.~string_type(); | ||
95 | |||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | binding& binding::operator=(const binding& other) | ||
102 | { | ||
103 | this->~binding(); | ||
104 | |||
105 | _type = other._type; | ||
106 | |||
107 | switch (_type) | ||
108 | { | ||
109 | case type::integer: | ||
110 | { | ||
111 | _integer = other._integer; | ||
112 | |||
113 | break; | ||
114 | } | ||
115 | |||
116 | case type::string: | ||
117 | { | ||
118 | new(&_string) std::string(other._string); | ||
119 | |||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | return *this; | ||
125 | } | ||
126 | |||
127 | binding::binding(int _arg) | ||
128 | { | ||
129 | _type = type::integer; | ||
130 | _integer = _arg; | ||
131 | } | ||
132 | |||
133 | int binding::get_integer() const | ||
134 | { | ||
135 | assert(_type == type::integer); | ||
136 | |||
137 | return _integer; | ||
138 | } | ||
139 | |||
140 | void binding::set_integer(int _arg) | ||
141 | { | ||
142 | *this = binding(_arg); | ||
143 | } | ||
144 | |||
145 | binding& binding::operator=(int _arg) | ||
146 | { | ||
147 | *this = binding(_arg); | ||
148 | |||
149 | return *this; | ||
150 | } | ||
151 | |||
152 | binding::binding(std::string _arg) | ||
153 | { | ||
154 | _type = type::string; | ||
155 | new(&_string) std::string(_arg); | ||
156 | } | ||
157 | |||
158 | std::string binding::get_string() const | ||
159 | { | ||
160 | assert(_type == type::string); | ||
161 | |||
162 | return _string; | ||
163 | } | ||
164 | |||
165 | void binding::set_string(std::string _arg) | ||
166 | { | ||
167 | *this = binding(_arg); | ||
168 | } | ||
169 | |||
170 | binding& binding::operator=(std::string _arg) | ||
171 | { | ||
172 | *this = binding(_arg); | ||
173 | |||
174 | return *this; | ||
175 | } | ||
176 | |||
60 | }; | 177 | }; |
diff --git a/lib/data.h b/lib/data.h index 0d599c4..b8b12b9 100644 --- a/lib/data.h +++ b/lib/data.h | |||
@@ -343,6 +343,38 @@ namespace verbly { | |||
343 | }; | 343 | }; |
344 | }; | 344 | }; |
345 | 345 | ||
346 | class binding { | ||
347 | public: | ||
348 | enum class type { | ||
349 | integer, | ||
350 | string | ||
351 | }; | ||
352 | |||
353 | type get_type() const; | ||
354 | binding(const binding& other); | ||
355 | ~binding(); | ||
356 | binding& operator=(const binding& other); | ||
357 | |||
358 | // Integer | ||
359 | binding(int _arg); | ||
360 | int get_integer() const; | ||
361 | void set_integer(int _arg); | ||
362 | binding& operator=(int _arg); | ||
363 | |||
364 | // String | ||
365 | binding(std::string _arg); | ||
366 | std::string get_string() const; | ||
367 | void set_string(std::string _arg); | ||
368 | binding& operator=(std::string _arg); | ||
369 | |||
370 | private: | ||
371 | union { | ||
372 | int _integer; | ||
373 | std::string _string; | ||
374 | }; | ||
375 | type _type; | ||
376 | }; | ||
377 | |||
346 | }; | 378 | }; |
347 | 379 | ||
348 | #endif /* end of include guard: DATA_H_C4AEC3DD */ | 380 | #endif /* end of include guard: DATA_H_C4AEC3DD */ |
diff --git a/lib/frame_query.cpp b/lib/frame_query.cpp index 6583da4..3c4a3e8 100644 --- a/lib/frame_query.cpp +++ b/lib/frame_query.cpp | |||
@@ -37,13 +37,19 @@ namespace verbly { | |||
37 | { | 37 | { |
38 | std::stringstream construct; | 38 | std::stringstream construct; |
39 | construct << "SELECT frames.data, groups.data FROM frames INNER JOIN groups ON frames.group_id = groups.group_id"; | 39 | construct << "SELECT frames.data, groups.data FROM frames INNER JOIN groups ON frames.group_id = groups.group_id"; |
40 | std::list<binding> bindings; | ||
40 | 41 | ||
41 | if (!_for_verb.empty()) | 42 | if (!_for_verb.empty()) |
42 | { | 43 | { |
43 | std::list<std::string> clauses(_for_verb.size(), "verb_id = @VERID"); | 44 | std::list<std::string> clauses(_for_verb.size(), "verb_id = ?"); |
44 | construct << " WHERE frames.group_id IN (SELECT group_id FROM verb_groups WHERE "; | 45 | construct << " WHERE frames.group_id IN (SELECT group_id FROM verb_groups WHERE "; |
45 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | 46 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); |
46 | construct << ")"; | 47 | construct << ")"; |
48 | |||
49 | for (auto v : _for_verb) | ||
50 | { | ||
51 | bindings.emplace_back(v._id); | ||
52 | } | ||
47 | } | 53 | } |
48 | 54 | ||
49 | sqlite3_stmt* ppstmt; | 55 | sqlite3_stmt* ppstmt; |
@@ -53,9 +59,27 @@ namespace verbly { | |||
53 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | 59 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); |
54 | } | 60 | } |
55 | 61 | ||
56 | for (auto verb : _for_verb) | 62 | int i = 1; |
63 | for (auto& binding : bindings) | ||
57 | { | 64 | { |
58 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VERID"), verb._id); | 65 | switch (binding.get_type()) |
66 | { | ||
67 | case binding::type::integer: | ||
68 | { | ||
69 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
70 | |||
71 | break; | ||
72 | } | ||
73 | |||
74 | case binding::type::string: | ||
75 | { | ||
76 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); | ||
77 | |||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | i++; | ||
59 | } | 83 | } |
60 | 84 | ||
61 | std::list<frame> output; | 85 | std::list<frame> output; |
diff --git a/lib/noun.cpp b/lib/noun.cpp index 71c9af0..d8b34c9 100644 --- a/lib/noun.cpp +++ b/lib/noun.cpp | |||
@@ -34,6 +34,13 @@ namespace verbly { | |||
34 | 34 | ||
35 | return _plural; | 35 | return _plural; |
36 | } | 36 | } |
37 | |||
38 | int noun::wnid() const | ||
39 | { | ||
40 | assert(_valid == true); | ||
41 | |||
42 | return _wnid; | ||
43 | } | ||
37 | 44 | ||
38 | bool noun::has_plural_form() const | 45 | bool noun::has_plural_form() const |
39 | { | 46 | { |
@@ -196,6 +203,16 @@ namespace verbly { | |||
196 | return _data->adjectives().variant_of(*this); | 203 | return _data->adjectives().variant_of(*this); |
197 | } | 204 | } |
198 | 205 | ||
206 | std::string noun::imagenet_url() const | ||
207 | { | ||
208 | std::stringstream url; | ||
209 | url << "http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=n"; | ||
210 | url.width(8); | ||
211 | url.fill('0'); | ||
212 | url << (_wnid % 100000000); | ||
213 | return url.str(); | ||
214 | } | ||
215 | |||
199 | bool noun::operator<(const noun& other) const | 216 | bool noun::operator<(const noun& other) const |
200 | { | 217 | { |
201 | return _id < other._id; | 218 | return _id < other._id; |
diff --git a/lib/noun.h b/lib/noun.h index 969d2c8..bd71e57 100644 --- a/lib/noun.h +++ b/lib/noun.h | |||
@@ -7,6 +7,7 @@ namespace verbly { | |||
7 | private: | 7 | private: |
8 | std::string _singular; | 8 | std::string _singular; |
9 | std::string _plural; | 9 | std::string _plural; |
10 | int _wnid; | ||
10 | 11 | ||
11 | friend class noun_query; | 12 | friend class noun_query; |
12 | 13 | ||
@@ -17,6 +18,7 @@ namespace verbly { | |||
17 | std::string base_form() const; | 18 | std::string base_form() const; |
18 | std::string singular_form() const; | 19 | std::string singular_form() const; |
19 | std::string plural_form() const; | 20 | std::string plural_form() const; |
21 | int wnid() const; | ||
20 | 22 | ||
21 | bool has_plural_form() const; | 23 | bool has_plural_form() const; |
22 | 24 | ||
@@ -43,6 +45,8 @@ namespace verbly { | |||
43 | adjective_query pertainyms() const; | 45 | adjective_query pertainyms() const; |
44 | adjective_query variations() const; | 46 | adjective_query variations() const; |
45 | 47 | ||
48 | std::string imagenet_url() const; | ||
49 | |||
46 | bool operator<(const noun& other) const; | 50 | bool operator<(const noun& other) const; |
47 | }; | 51 | }; |
48 | 52 | ||
diff --git a/lib/noun_query.cpp b/lib/noun_query.cpp index 83bb47d..19a1297 100644 --- a/lib/noun_query.cpp +++ b/lib/noun_query.cpp | |||
@@ -370,6 +370,21 @@ namespace verbly { | |||
370 | 370 | ||
371 | return *this; | 371 | return *this; |
372 | } | 372 | } |
373 | |||
374 | noun_query& noun_query::at_least_n_images(int _arg) | ||
375 | { | ||
376 | _at_least_n_images = _arg; | ||
377 | |||
378 | return *this; | ||
379 | } | ||
380 | |||
381 | noun_query& noun_query::with_wnid(int _arg) | ||
382 | { | ||
383 | _with_wnid.insert(_arg); | ||
384 | |||
385 | return *this; | ||
386 | } | ||
387 | |||
373 | /* | 388 | /* |
374 | noun_query& noun_query::derived_from(const word& _w) | 389 | noun_query& noun_query::derived_from(const word& _w) |
375 | { | 390 | { |
@@ -457,8 +472,9 @@ namespace verbly { | |||
457 | construct << " "; | 472 | construct << " "; |
458 | } | 473 | } |
459 | 474 | ||
460 | construct << "SELECT noun_id, singular, plural FROM nouns"; | 475 | construct << "SELECT noun_id, singular, plural, wnid FROM nouns"; |
461 | std::list<std::string> conditions; | 476 | std::list<std::string> conditions; |
477 | std::list<binding> bindings; | ||
462 | 478 | ||
463 | if (_has_prn) | 479 | if (_has_prn) |
464 | { | 480 | { |
@@ -467,21 +483,32 @@ namespace verbly { | |||
467 | 483 | ||
468 | if (!_rhymes.empty()) | 484 | if (!_rhymes.empty()) |
469 | { | 485 | { |
470 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | 486 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); |
471 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | 487 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; |
472 | conditions.push_back(cond); | 488 | conditions.push_back(cond); |
489 | |||
490 | for (auto rhyme : _rhymes) | ||
491 | { | ||
492 | bindings.emplace_back("%" + rhyme); | ||
493 | } | ||
473 | } | 494 | } |
474 | 495 | ||
475 | for (auto except : _except) | 496 | for (auto except : _except) |
476 | { | 497 | { |
477 | conditions.push_back("noun_id != @EXCID"); | 498 | conditions.push_back("noun_id != ?"); |
499 | bindings.emplace_back(except._id); | ||
478 | } | 500 | } |
479 | 501 | ||
480 | if (!_with_singular_form.empty()) | 502 | if (!_with_singular_form.empty()) |
481 | { | 503 | { |
482 | std::list<std::string> clauses(_with_singular_form.size(), "singular = @SFORM"); | 504 | std::list<std::string> clauses(_with_singular_form.size(), "singular = ?"); |
483 | std::string cond = "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | 505 | std::string cond = "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; |
484 | conditions.push_back(cond); | 506 | conditions.push_back(cond); |
507 | |||
508 | for (auto form : _with_singular_form) | ||
509 | { | ||
510 | bindings.emplace_back(form); | ||
511 | } | ||
485 | } | 512 | } |
486 | 513 | ||
487 | if (!_with_prefix.empty()) | 514 | if (!_with_prefix.empty()) |
@@ -491,11 +518,13 @@ namespace verbly { | |||
491 | { | 518 | { |
492 | case filter<std::string>::type::singleton: | 519 | case filter<std::string>::type::singleton: |
493 | { | 520 | { |
521 | bindings.emplace_back(f.get_elem() + "%"); | ||
522 | |||
494 | if (notlogic == f.get_notlogic()) | 523 | if (notlogic == f.get_notlogic()) |
495 | { | 524 | { |
496 | return "singular LIKE @PREFIX"; | 525 | return "singular LIKE ?"; |
497 | } else { | 526 | } else { |
498 | return "singular NOT LIKE @PREFIX"; | 527 | return "singular NOT LIKE ?"; |
499 | } | 528 | } |
500 | } | 529 | } |
501 | 530 | ||
@@ -528,11 +557,13 @@ namespace verbly { | |||
528 | { | 557 | { |
529 | case filter<std::string>::type::singleton: | 558 | case filter<std::string>::type::singleton: |
530 | { | 559 | { |
560 | bindings.emplace_back("%" + f.get_elem()); | ||
561 | |||
531 | if (notlogic == f.get_notlogic()) | 562 | if (notlogic == f.get_notlogic()) |
532 | { | 563 | { |
533 | return "singular LIKE @SUFFIX"; | 564 | return "singular LIKE ?"; |
534 | } else { | 565 | } else { |
535 | return "singular NOT LIKE @SUFFIX"; | 566 | return "singular NOT LIKE ?"; |
536 | } | 567 | } |
537 | } | 568 | } |
538 | 569 | ||
@@ -560,7 +591,8 @@ namespace verbly { | |||
560 | 591 | ||
561 | if (_with_complexity != unlimited) | 592 | if (_with_complexity != unlimited) |
562 | { | 593 | { |
563 | conditions.push_back("complexity = @COMPLEX"); | 594 | conditions.push_back("complexity = ?"); |
595 | bindings.emplace_back(_with_complexity); | ||
564 | } | 596 | } |
565 | 597 | ||
566 | if (_is_hypernym) | 598 | if (_is_hypernym) |
@@ -585,11 +617,13 @@ namespace verbly { | |||
585 | { | 617 | { |
586 | case filter<noun>::type::singleton: | 618 | case filter<noun>::type::singleton: |
587 | { | 619 | { |
620 | bindings.emplace_back(f.get_elem()._id); | ||
621 | |||
588 | if (notlogic == f.get_notlogic()) | 622 | if (notlogic == f.get_notlogic()) |
589 | { | 623 | { |
590 | return "hyponym_id = @HYPO"; | 624 | return "hyponym_id = ?"; |
591 | } else { | 625 | } else { |
592 | return "hyponym_id != @HYPO"; | 626 | return "hyponym_id != ?"; |
593 | } | 627 | } |
594 | } | 628 | } |
595 | 629 | ||
@@ -713,11 +747,13 @@ namespace verbly { | |||
713 | { | 747 | { |
714 | case filter<noun>::type::singleton: | 748 | case filter<noun>::type::singleton: |
715 | { | 749 | { |
750 | bindings.emplace_back(f.get_elem()._id); | ||
751 | |||
716 | if (notlogic == f.get_notlogic()) | 752 | if (notlogic == f.get_notlogic()) |
717 | { | 753 | { |
718 | return "hypernym_id = @HYPER"; | 754 | return "hypernym_id = ?"; |
719 | } else { | 755 | } else { |
720 | return "hypernym_id != @HYPER"; | 756 | return "hypernym_id != ?"; |
721 | } | 757 | } |
722 | } | 758 | } |
723 | 759 | ||
@@ -767,11 +803,13 @@ namespace verbly { | |||
767 | { | 803 | { |
768 | case filter<noun>::type::singleton: | 804 | case filter<noun>::type::singleton: |
769 | { | 805 | { |
806 | bindings.emplace_back(f.get_elem()._id); | ||
807 | |||
770 | if (notlogic == f.get_notlogic()) | 808 | if (notlogic == f.get_notlogic()) |
771 | { | 809 | { |
772 | return "holonym_id = @PHOLO"; | 810 | return "holonym_id = ?"; |
773 | } else { | 811 | } else { |
774 | return "holonym_id != @PHOLO"; | 812 | return "holonym_id != ?"; |
775 | } | 813 | } |
776 | } | 814 | } |
777 | 815 | ||
@@ -858,11 +896,13 @@ namespace verbly { | |||
858 | { | 896 | { |
859 | case filter<noun>::type::singleton: | 897 | case filter<noun>::type::singleton: |
860 | { | 898 | { |
899 | bindings.emplace_back(f.get_elem()._id); | ||
900 | |||
861 | if (notlogic == f.get_notlogic()) | 901 | if (notlogic == f.get_notlogic()) |
862 | { | 902 | { |
863 | return "meronym_id = @PMERO"; | 903 | return "meronym_id = ?"; |
864 | } else { | 904 | } else { |
865 | return "meronym_id != @PMERO"; | 905 | return "meronym_id != ?"; |
866 | } | 906 | } |
867 | } | 907 | } |
868 | 908 | ||
@@ -949,11 +989,13 @@ namespace verbly { | |||
949 | { | 989 | { |
950 | case filter<noun>::type::singleton: | 990 | case filter<noun>::type::singleton: |
951 | { | 991 | { |
992 | bindings.emplace_back(f.get_elem()._id); | ||
993 | |||
952 | if (notlogic == f.get_notlogic()) | 994 | if (notlogic == f.get_notlogic()) |
953 | { | 995 | { |
954 | return "holonym_id = @SHOLO"; | 996 | return "holonym_id = ?"; |
955 | } else { | 997 | } else { |
956 | return "holonym_id != @SHOLO"; | 998 | return "holonym_id != ?"; |
957 | } | 999 | } |
958 | } | 1000 | } |
959 | 1001 | ||
@@ -1040,11 +1082,13 @@ namespace verbly { | |||
1040 | { | 1082 | { |
1041 | case filter<noun>::type::singleton: | 1083 | case filter<noun>::type::singleton: |
1042 | { | 1084 | { |
1085 | bindings.emplace_back(f.get_elem()._id); | ||
1086 | |||
1043 | if (notlogic == f.get_notlogic()) | 1087 | if (notlogic == f.get_notlogic()) |
1044 | { | 1088 | { |
1045 | return "meronym_id = @SMERO"; | 1089 | return "meronym_id = ?"; |
1046 | } else { | 1090 | } else { |
1047 | return "meronym_id != @SMERO"; | 1091 | return "meronym_id != ?"; |
1048 | } | 1092 | } |
1049 | } | 1093 | } |
1050 | 1094 | ||
@@ -1131,11 +1175,13 @@ namespace verbly { | |||
1131 | { | 1175 | { |
1132 | case filter<noun>::type::singleton: | 1176 | case filter<noun>::type::singleton: |
1133 | { | 1177 | { |
1178 | bindings.emplace_back(f.get_elem()._id); | ||
1179 | |||
1134 | if (notlogic == f.get_notlogic()) | 1180 | if (notlogic == f.get_notlogic()) |
1135 | { | 1181 | { |
1136 | return "holonym_id = @MHOLO"; | 1182 | return "holonym_id = ?"; |
1137 | } else { | 1183 | } else { |
1138 | return "holonym_id != @MHOLO"; | 1184 | return "holonym_id != ?"; |
1139 | } | 1185 | } |
1140 | } | 1186 | } |
1141 | 1187 | ||
@@ -1222,11 +1268,13 @@ namespace verbly { | |||
1222 | { | 1268 | { |
1223 | case filter<noun>::type::singleton: | 1269 | case filter<noun>::type::singleton: |
1224 | { | 1270 | { |
1271 | bindings.emplace_back(f.get_elem()._id); | ||
1272 | |||
1225 | if (notlogic == f.get_notlogic()) | 1273 | if (notlogic == f.get_notlogic()) |
1226 | { | 1274 | { |
1227 | return "meronym_id = @MMERO"; | 1275 | return "meronym_id = ?"; |
1228 | } else { | 1276 | } else { |
1229 | return "meronym_id != @MMERO"; | 1277 | return "meronym_id != ?"; |
1230 | } | 1278 | } |
1231 | } | 1279 | } |
1232 | 1280 | ||
@@ -1323,11 +1371,13 @@ namespace verbly { | |||
1323 | { | 1371 | { |
1324 | case filter<noun>::type::singleton: | 1372 | case filter<noun>::type::singleton: |
1325 | { | 1373 | { |
1374 | bindings.emplace_back(f.get_elem()._id); | ||
1375 | |||
1326 | if (notlogic == f.get_notlogic()) | 1376 | if (notlogic == f.get_notlogic()) |
1327 | { | 1377 | { |
1328 | return "class_id = @CLSID"; | 1378 | return "class_id = ?"; |
1329 | } else { | 1379 | } else { |
1330 | return "class_id != @CLSID"; | 1380 | return "class_id != ?"; |
1331 | } | 1381 | } |
1332 | } | 1382 | } |
1333 | 1383 | ||
@@ -1377,11 +1427,13 @@ namespace verbly { | |||
1377 | { | 1427 | { |
1378 | case filter<noun>::type::singleton: | 1428 | case filter<noun>::type::singleton: |
1379 | { | 1429 | { |
1430 | bindings.emplace_back(f.get_elem()._id); | ||
1431 | |||
1380 | if (notlogic == f.get_notlogic()) | 1432 | if (notlogic == f.get_notlogic()) |
1381 | { | 1433 | { |
1382 | return "instance_id = @INSID"; | 1434 | return "instance_id = ?"; |
1383 | } else { | 1435 | } else { |
1384 | return "instance_id != @INSID"; | 1436 | return "instance_id != ?"; |
1385 | } | 1437 | } |
1386 | } | 1438 | } |
1387 | 1439 | ||
@@ -1431,11 +1483,13 @@ namespace verbly { | |||
1431 | { | 1483 | { |
1432 | case filter<noun>::type::singleton: | 1484 | case filter<noun>::type::singleton: |
1433 | { | 1485 | { |
1486 | bindings.emplace_back(f.get_elem()._id); | ||
1487 | |||
1434 | if (notlogic == f.get_notlogic()) | 1488 | if (notlogic == f.get_notlogic()) |
1435 | { | 1489 | { |
1436 | return "noun_1_id = @SYNID"; | 1490 | return "noun_1_id = ?"; |
1437 | } else { | 1491 | } else { |
1438 | return "noun_1_id != @SYNID"; | 1492 | return "noun_1_id != ?"; |
1439 | } | 1493 | } |
1440 | } | 1494 | } |
1441 | 1495 | ||
@@ -1485,11 +1539,13 @@ namespace verbly { | |||
1485 | { | 1539 | { |
1486 | case filter<noun>::type::singleton: | 1540 | case filter<noun>::type::singleton: |
1487 | { | 1541 | { |
1542 | bindings.emplace_back(f.get_elem()._id); | ||
1543 | |||
1488 | if (notlogic == f.get_notlogic()) | 1544 | if (notlogic == f.get_notlogic()) |
1489 | { | 1545 | { |
1490 | return "noun_1_id = @ANTID"; | 1546 | return "noun_1_id = ?"; |
1491 | } else { | 1547 | } else { |
1492 | return "noun_1_id != @ANTID"; | 1548 | return "noun_1_id != ?"; |
1493 | } | 1549 | } |
1494 | } | 1550 | } |
1495 | 1551 | ||
@@ -1539,11 +1595,13 @@ namespace verbly { | |||
1539 | { | 1595 | { |
1540 | case filter<adjective>::type::singleton: | 1596 | case filter<adjective>::type::singleton: |
1541 | { | 1597 | { |
1598 | bindings.emplace_back(f.get_elem()._id); | ||
1599 | |||
1542 | if (notlogic == f.get_notlogic()) | 1600 | if (notlogic == f.get_notlogic()) |
1543 | { | 1601 | { |
1544 | return "pertainym_id = @PERID"; | 1602 | return "pertainym_id = ?"; |
1545 | } else { | 1603 | } else { |
1546 | return "pertainym_id != @PERID"; | 1604 | return "pertainym_id != ?"; |
1547 | } | 1605 | } |
1548 | } | 1606 | } |
1549 | 1607 | ||
@@ -1593,11 +1651,13 @@ namespace verbly { | |||
1593 | { | 1651 | { |
1594 | case filter<adjective>::type::singleton: | 1652 | case filter<adjective>::type::singleton: |
1595 | { | 1653 | { |
1654 | bindings.emplace_back(f.get_elem()._id); | ||
1655 | |||
1596 | if (notlogic == f.get_notlogic()) | 1656 | if (notlogic == f.get_notlogic()) |
1597 | { | 1657 | { |
1598 | return "adjective_id = @VALID"; | 1658 | return "adjective_id = ?"; |
1599 | } else { | 1659 | } else { |
1600 | return "adjective_id != @VALID"; | 1660 | return "adjective_id != ?"; |
1601 | } | 1661 | } |
1602 | } | 1662 | } |
1603 | 1663 | ||
@@ -1624,6 +1684,25 @@ namespace verbly { | |||
1624 | cond << ")"; | 1684 | cond << ")"; |
1625 | conditions.push_back(cond.str()); | 1685 | conditions.push_back(cond.str()); |
1626 | } | 1686 | } |
1687 | |||
1688 | if (_at_least_n_images != unlimited) | ||
1689 | { | ||
1690 | conditions.push_back("images >= ?"); | ||
1691 | bindings.emplace_back(_at_least_n_images); | ||
1692 | } | ||
1693 | |||
1694 | if (!_with_wnid.empty()) | ||
1695 | { | ||
1696 | std::vector<std::string> clauses(_with_wnid.size(), "wnid = ?"); | ||
1697 | std::string cond = verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | ||
1698 | conditions.push_back("(" + cond + ")"); | ||
1699 | |||
1700 | for (auto wnid : _with_wnid) | ||
1701 | { | ||
1702 | bindings.emplace_back(wnid); | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1627 | /* | 1706 | /* |
1628 | if (!_derived_from_adjective.empty()) | 1707 | if (!_derived_from_adjective.empty()) |
1629 | { | 1708 | { |
@@ -1690,114 +1769,29 @@ namespace verbly { | |||
1690 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | 1769 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); |
1691 | } | 1770 | } |
1692 | 1771 | ||
1693 | if (!_rhymes.empty()) | 1772 | int i = 1; |
1773 | for (auto& binding : bindings) | ||
1694 | { | 1774 | { |
1695 | int i = 0; | 1775 | switch (binding.get_type()) |
1696 | for (auto rhyme : _rhymes) | ||
1697 | { | 1776 | { |
1698 | std::string rhymer = "%" + rhyme; | 1777 | case binding::type::integer: |
1699 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | 1778 | { |
1779 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
1780 | |||
1781 | break; | ||
1782 | } | ||
1700 | 1783 | ||
1701 | i++; | 1784 | case binding::type::string: |
1785 | { | ||
1786 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); | ||
1787 | |||
1788 | break; | ||
1789 | } | ||
1702 | } | 1790 | } |
1791 | |||
1792 | i++; | ||
1703 | } | 1793 | } |
1704 | 1794 | ||
1705 | for (auto except : _except) | ||
1706 | { | ||
1707 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
1708 | } | ||
1709 | |||
1710 | for (auto sform : _with_singular_form) | ||
1711 | { | ||
1712 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SFORM"), sform.c_str(), sform.size(), SQLITE_STATIC); | ||
1713 | } | ||
1714 | |||
1715 | for (auto prefix : _with_prefix.inorder_flatten()) | ||
1716 | { | ||
1717 | std::string pfat = prefix + "%"; | ||
1718 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PREFIX"), pfat.c_str(), pfat.length(), SQLITE_STATIC); | ||
1719 | } | ||
1720 | |||
1721 | for (auto suffix : _with_suffix.inorder_flatten()) | ||
1722 | { | ||
1723 | std::string pfat = "%" + suffix; | ||
1724 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SUFFIX"), pfat.c_str(), pfat.length(), SQLITE_STATIC); | ||
1725 | } | ||
1726 | |||
1727 | if (_with_complexity != unlimited) | ||
1728 | { | ||
1729 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@COMPLEX"), _with_complexity); | ||
1730 | } | ||
1731 | |||
1732 | for (auto hyponym : _hypernym_of.inorder_flatten()) | ||
1733 | { | ||
1734 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); | ||
1735 | } | ||
1736 | |||
1737 | for (auto hypernym : _hyponym_of.inorder_flatten()) | ||
1738 | { | ||
1739 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); | ||
1740 | } | ||
1741 | |||
1742 | for (auto holonym : _part_meronym_of.inorder_flatten()) | ||
1743 | { | ||
1744 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); | ||
1745 | } | ||
1746 | |||
1747 | for (auto meronym : _part_holonym_of.inorder_flatten()) | ||
1748 | { | ||
1749 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); | ||
1750 | } | ||
1751 | |||
1752 | for (auto holonym : _substance_meronym_of.inorder_flatten()) | ||
1753 | { | ||
1754 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); | ||
1755 | } | ||
1756 | |||
1757 | for (auto meronym : _substance_holonym_of.inorder_flatten()) | ||
1758 | { | ||
1759 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); | ||
1760 | } | ||
1761 | |||
1762 | for (auto holonym : _member_meronym_of.inorder_flatten()) | ||
1763 | { | ||
1764 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); | ||
1765 | } | ||
1766 | |||
1767 | for (auto meronym : _member_holonym_of.inorder_flatten()) | ||
1768 | { | ||
1769 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); | ||
1770 | } | ||
1771 | |||
1772 | for (auto cls : _instance_of.inorder_flatten()) | ||
1773 | { | ||
1774 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); | ||
1775 | } | ||
1776 | |||
1777 | for (auto inst : _class_of.inorder_flatten()) | ||
1778 | { | ||
1779 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); | ||
1780 | } | ||
1781 | |||
1782 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
1783 | { | ||
1784 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
1785 | } | ||
1786 | |||
1787 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
1788 | { | ||
1789 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
1790 | } | ||
1791 | |||
1792 | for (auto pertainym : _anti_pertainym_of.inorder_flatten()) | ||
1793 | { | ||
1794 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); | ||
1795 | } | ||
1796 | |||
1797 | for (auto value : _attribute_of.inorder_flatten()) | ||
1798 | { | ||
1799 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); | ||
1800 | } | ||
1801 | /* | 1795 | /* |
1802 | for (auto adj : _derived_from_adjective) | 1796 | for (auto adj : _derived_from_adjective) |
1803 | { | 1797 | { |
@@ -1839,6 +1833,8 @@ namespace verbly { | |||
1839 | { | 1833 | { |
1840 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | 1834 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); |
1841 | } | 1835 | } |
1836 | |||
1837 | tnc._wnid = sqlite3_column_int(ppstmt, 3); | ||
1842 | 1838 | ||
1843 | output.push_back(tnc); | 1839 | output.push_back(tnc); |
1844 | } | 1840 | } |
diff --git a/lib/noun_query.h b/lib/noun_query.h index 5b73f8d..8768f5d 100644 --- a/lib/noun_query.h +++ b/lib/noun_query.h | |||
@@ -72,6 +72,9 @@ namespace verbly { | |||
72 | noun_query& is_attribute(); | 72 | noun_query& is_attribute(); |
73 | noun_query& attribute_of(filter<adjective> _f); | 73 | noun_query& attribute_of(filter<adjective> _f); |
74 | 74 | ||
75 | noun_query& at_least_n_images(int _arg); | ||
76 | noun_query& with_wnid(int _arg); | ||
77 | |||
75 | /* noun_query& derived_from(const word& _w); | 78 | /* noun_query& derived_from(const word& _w); |
76 | noun_query& not_derived_from(const word& _w);*/ | 79 | noun_query& not_derived_from(const word& _w);*/ |
77 | 80 | ||
@@ -146,6 +149,9 @@ namespace verbly { | |||
146 | bool _is_attribute = false; | 149 | bool _is_attribute = false; |
147 | filter<adjective> _attribute_of; | 150 | filter<adjective> _attribute_of; |
148 | 151 | ||
152 | int _at_least_n_images = unlimited; | ||
153 | std::set<int> _with_wnid; | ||
154 | |||
149 | /* std::list<adjective> _derived_from_adjective; | 155 | /* std::list<adjective> _derived_from_adjective; |
150 | std::list<adjective> _not_derived_from_adjective; | 156 | std::list<adjective> _not_derived_from_adjective; |
151 | std::list<adverb> _derived_from_adverb; | 157 | std::list<adverb> _derived_from_adverb; |
diff --git a/lib/preposition.cpp b/lib/preposition.cpp index c619bbf..8df13aa 100644 --- a/lib/preposition.cpp +++ b/lib/preposition.cpp | |||
@@ -37,13 +37,19 @@ namespace verbly { | |||
37 | { | 37 | { |
38 | std::stringstream construct; | 38 | std::stringstream construct; |
39 | construct << "SELECT form FROM prepositions"; | 39 | construct << "SELECT form FROM prepositions"; |
40 | std::list<binding> bindings; | ||
40 | 41 | ||
41 | if (!_in_group.empty()) | 42 | if (!_in_group.empty()) |
42 | { | 43 | { |
43 | std::list<std::string> clauses(_in_group.size(), "groupname = @GNAME"); | 44 | std::list<std::string> clauses(_in_group.size(), "groupname = ?"); |
44 | construct << " WHERE preposition_id IN (SELECT preposition_id FROM preposition_groups WHERE "; | 45 | construct << " WHERE preposition_id IN (SELECT preposition_id FROM preposition_groups WHERE "; |
45 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | 46 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); |
46 | construct << ")"; | 47 | construct << ")"; |
48 | |||
49 | for (auto g : _in_group) | ||
50 | { | ||
51 | bindings.emplace_back(g); | ||
52 | } | ||
47 | } | 53 | } |
48 | 54 | ||
49 | if (_random) | 55 | if (_random) |
@@ -63,9 +69,27 @@ namespace verbly { | |||
63 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | 69 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); |
64 | } | 70 | } |
65 | 71 | ||
66 | for (auto& group : _in_group) | 72 | int i = 1; |
73 | for (auto& binding : bindings) | ||
67 | { | 74 | { |
68 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GNAME"), group.c_str(), group.length(), SQLITE_STATIC); | 75 | switch (binding.get_type()) |
76 | { | ||
77 | case binding::type::integer: | ||
78 | { | ||
79 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
80 | |||
81 | break; | ||
82 | } | ||
83 | |||
84 | case binding::type::string: | ||
85 | { | ||
86 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); | ||
87 | |||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | i++; | ||
69 | } | 93 | } |
70 | 94 | ||
71 | std::list<preposition> output; | 95 | std::list<preposition> output; |
diff --git a/lib/verb_query.cpp b/lib/verb_query.cpp index 173a04e..929ecc7 100644 --- a/lib/verb_query.cpp +++ b/lib/verb_query.cpp | |||
@@ -65,6 +65,7 @@ namespace verbly { | |||
65 | std::stringstream construct; | 65 | std::stringstream construct; |
66 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; | 66 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; |
67 | std::list<std::string> conditions; | 67 | std::list<std::string> conditions; |
68 | std::list<binding> bindings; | ||
68 | 69 | ||
69 | if (_has_prn) | 70 | if (_has_prn) |
70 | { | 71 | { |
@@ -73,14 +74,20 @@ namespace verbly { | |||
73 | 74 | ||
74 | if (!_rhymes.empty()) | 75 | if (!_rhymes.empty()) |
75 | { | 76 | { |
76 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | 77 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); |
77 | std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | 78 | 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 | conditions.push_back(cond); |
80 | |||
81 | for (auto rhyme : _rhymes) | ||
82 | { | ||
83 | bindings.emplace_back("%" + rhyme); | ||
84 | } | ||
79 | } | 85 | } |
80 | 86 | ||
81 | for (auto except : _except) | 87 | for (auto except : _except) |
82 | { | 88 | { |
83 | conditions.push_back("verb_id != @EXCID"); | 89 | conditions.push_back("verb_id != ?"); |
90 | bindings.emplace_back(except._id); | ||
84 | } | 91 | } |
85 | 92 | ||
86 | if (!_has_frames) | 93 | if (!_has_frames) |
@@ -111,21 +118,27 @@ namespace verbly { | |||
111 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | 118 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); |
112 | } | 119 | } |
113 | 120 | ||
114 | if (!_rhymes.empty()) | 121 | int i = 1; |
122 | for (auto& binding : bindings) | ||
115 | { | 123 | { |
116 | int i = 0; | 124 | switch (binding.get_type()) |
117 | for (auto rhyme : _rhymes) | ||
118 | { | 125 | { |
119 | std::string rhymer = "%" + rhyme; | 126 | case binding::type::integer: |
120 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | 127 | { |
128 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
129 | |||
130 | break; | ||
131 | } | ||
121 | 132 | ||
122 | i++; | 133 | case binding::type::string: |
134 | { | ||
135 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); | ||
136 | |||
137 | break; | ||
138 | } | ||
123 | } | 139 | } |
124 | } | 140 | |
125 | 141 | i++; | |
126 | for (auto except : _except) | ||
127 | { | ||
128 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
129 | } | 142 | } |
130 | 143 | ||
131 | std::list<verb> output; | 144 | std::list<verb> output; |