summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-04-15 17:24:44 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-04-15 17:24:44 -0400
commit040ee58fecdc9c478004bc2e554e1ae126ec4602 (patch)
tree672a75690952ba8055ab9765ba0a475e056e35d4
parent3a225f5eb709262b9d44d49519136ea9a2a71000 (diff)
downloadverbly-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.cpp57
-rw-r--r--generator/schema.sql4
-rw-r--r--lib/adjective_query.cpp147
-rw-r--r--lib/adverb_query.cpp103
-rw-r--r--lib/data.cpp117
-rw-r--r--lib/data.h32
-rw-r--r--lib/frame_query.cpp30
-rw-r--r--lib/noun.cpp17
-rw-r--r--lib/noun.h4
-rw-r--r--lib/noun_query.cpp274
-rw-r--r--lib/noun_query.h6
-rw-r--r--lib/preposition.cpp30
-rw-r--r--lib/verb_query.cpp39
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;
81std::map<std::string, adjective_t> adjectives; 81std::map<std::string, adjective_t> adjectives;
82std::map<std::string, noun_t> nouns; 82std::map<std::string, noun_t> nouns;
83std::map<int, std::map<int, int>> wn; 83std::map<int, std::map<int, int>> wn;
84std::map<int, int> images;
84std::map<std::string, std::set<std::string>> pronunciations; 85std::map<std::string, std::set<std::string>> pronunciations;
85 86
86void print_usage() 87void 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
61DROP TABLE IF EXISTS `hypernymy`; 63DROP 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;