summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--generator/database.cpp14
-rw-r--r--generator/database.h2
-rw-r--r--generator/field.h12
-rw-r--r--generator/frame.h38
-rw-r--r--generator/generator.h108
-rw-r--r--generator/group.cpp46
-rw-r--r--generator/group.h52
-rw-r--r--generator/main.cpp2
-rw-r--r--generator/notion.cpp14
-rw-r--r--generator/notion.h8
-rw-r--r--generator/part.cpp134
-rw-r--r--generator/part.h74
-rw-r--r--generator/progress.h16
-rw-r--r--generator/word.cpp8
-rw-r--r--generator/word.h10
-rw-r--r--lib/binding.h14
-rw-r--r--lib/database.cpp14
-rw-r--r--lib/database.h18
-rw-r--r--lib/enums.h10
-rw-r--r--lib/field.cpp34
-rw-r--r--lib/lemma.cpp34
-rw-r--r--lib/lemma.h78
-rw-r--r--lib/pronunciation.cpp34
-rw-r--r--lib/query.h48
-rw-r--r--lib/role.h24
-rw-r--r--lib/selrestr.cpp102
-rw-r--r--lib/selrestr.h56
-rw-r--r--lib/statement.cpp290
-rw-r--r--lib/statement.h130
-rw-r--r--lib/util.h22
-rw-r--r--lib/word.cpp56
-rw-r--r--lib/word.h100
32 files changed, 801 insertions, 801 deletions
diff --git a/generator/database.cpp b/generator/database.cpp index c7e4cfa..188fa2a 100644 --- a/generator/database.cpp +++ b/generator/database.cpp
@@ -73,19 +73,19 @@ namespace verbly {
73 { 73 {
74 sqlite3_close_v2(ppdb_); 74 sqlite3_close_v2(ppdb_);
75 } 75 }
76 76
77 void database::runQuery(std::string query) 77 void database::runQuery(std::string query)
78 { 78 {
79 // This can only happen when doing bad things with move semantics. 79 // This can only happen when doing bad things with move semantics.
80 assert(ppdb_ != nullptr); 80 assert(ppdb_ != nullptr);
81 81
82 sqlite3_stmt* ppstmt; 82 sqlite3_stmt* ppstmt;
83 83
84 if (sqlite3_prepare_v2(ppdb_, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) 84 if (sqlite3_prepare_v2(ppdb_, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
85 { 85 {
86 throw sqlite3_error("Error writing to database", sqlite3_errmsg(ppdb_)); 86 throw sqlite3_error("Error writing to database", sqlite3_errmsg(ppdb_));
87 } 87 }
88 88
89 int result = sqlite3_step(ppstmt); 89 int result = sqlite3_step(ppstmt);
90 sqlite3_finalize(ppstmt); 90 sqlite3_finalize(ppstmt);
91 91
@@ -99,10 +99,10 @@ namespace verbly {
99 { 99 {
100 // This can only happen when doing bad things with move semantics. 100 // This can only happen when doing bad things with move semantics.
101 assert(ppdb_ != nullptr); 101 assert(ppdb_ != nullptr);
102 102
103 // This shouldn't happen. 103 // This shouldn't happen.
104 assert(!fields.empty()); 104 assert(!fields.empty());
105 105
106 std::list<std::string> fieldNames; 106 std::list<std::string> fieldNames;
107 std::list<std::string> qs; 107 std::list<std::string> qs;
108 for (field& f : fields) 108 for (field& f : fields)
@@ -110,7 +110,7 @@ namespace verbly {
110 fieldNames.push_back(f.getName()); 110 fieldNames.push_back(f.getName());
111 qs.push_back("?"); 111 qs.push_back("?");
112 } 112 }
113 113
114 std::ostringstream query; 114 std::ostringstream query;
115 query << "INSERT INTO "; 115 query << "INSERT INTO ";
116 query << table; 116 query << table;
@@ -119,7 +119,7 @@ namespace verbly {
119 query << ") VALUES ("; 119 query << ") VALUES (";
120 query << implode(std::begin(qs), std::end(qs), ", "); 120 query << implode(std::begin(qs), std::end(qs), ", ");
121 query << ")"; 121 query << ")";
122 122
123 std::string query_str = query.str(); 123 std::string query_str = query.str();
124 124
125 sqlite3_stmt* ppstmt; 125 sqlite3_stmt* ppstmt;
diff --git a/generator/database.h b/generator/database.h index 15cdff5..7906304 100644 --- a/generator/database.h +++ b/generator/database.h
@@ -52,7 +52,7 @@ namespace verbly {
52 ~database(); 52 ~database();
53 53
54 // Actions 54 // Actions
55 55
56 void runQuery(std::string query); 56 void runQuery(std::string query);
57 57
58 void insertIntoTable(std::string table, std::list<field> fields); 58 void insertIntoTable(std::string table, std::list<field> fields);
diff --git a/generator/field.h b/generator/field.h index 1fbabfc..aaca3fa 100644 --- a/generator/field.h +++ b/generator/field.h
@@ -32,27 +32,27 @@ namespace verbly {
32 ~field(); 32 ~field();
33 33
34 // Generic accessors 34 // Generic accessors
35 35
36 type getType() const 36 type getType() const
37 { 37 {
38 return type_; 38 return type_;
39 } 39 }
40 40
41 std::string getName() const 41 std::string getName() const
42 { 42 {
43 return name_; 43 return name_;
44 } 44 }
45 45
46 // Integer 46 // Integer
47 47
48 field(std::string name, int arg); 48 field(std::string name, int arg);
49 49
50 int getInteger() const; 50 int getInteger() const;
51 51
52 // String 52 // String
53 53
54 field(std::string name, std::string arg); 54 field(std::string name, std::string arg);
55 55
56 std::string getString() const; 56 std::string getString() const;
57 57
58 private: 58 private:
diff --git a/generator/frame.h b/generator/frame.h index 411ce6c..764564d 100644 --- a/generator/frame.h +++ b/generator/frame.h
@@ -6,53 +6,53 @@
6 6
7namespace verbly { 7namespace verbly {
8 namespace generator { 8 namespace generator {
9 9
10 class database; 10 class database;
11 11
12 class frame { 12 class frame {
13 public: 13 public:
14 14
15 // Aliases 15 // Aliases
16 16
17 using const_iterator = std::list<part>::const_iterator; 17 using const_iterator = std::list<part>::const_iterator;
18 18
19 // Constructor 19 // Constructor
20 20
21 frame(); 21 frame();
22 22
23 // Mutators 23 // Mutators
24 24
25 void push_back(part fp); 25 void push_back(part fp);
26 26
27 // Accessors 27 // Accessors
28 28
29 int getId() const 29 int getId() const
30 { 30 {
31 return id_; 31 return id_;
32 } 32 }
33 33
34 const_iterator begin() const 34 const_iterator begin() const
35 { 35 {
36 return std::begin(parts_); 36 return std::begin(parts_);
37 } 37 }
38 38
39 const_iterator end() const 39 const_iterator end() const
40 { 40 {
41 return std::end(parts_); 41 return std::end(parts_);
42 } 42 }
43 43
44 private: 44 private:
45 45
46 static int nextId_; 46 static int nextId_;
47 47
48 const int id_; 48 const int id_;
49 49
50 std::list<part> parts_; 50 std::list<part> parts_;
51 51
52 }; 52 };
53 53
54 database& operator<<(database& db, const frame& arg); 54 database& operator<<(database& db, const frame& arg);
55 55
56 }; 56 };
57}; 57};
58 58
diff --git a/generator/generator.h b/generator/generator.h index c829c21..8352693 100644 --- a/generator/generator.h +++ b/generator/generator.h
@@ -16,17 +16,17 @@
16#include "frame.h" 16#include "frame.h"
17 17
18namespace verbly { 18namespace verbly {
19 19
20 enum class part_of_speech; 20 enum class part_of_speech;
21 class selrestr; 21 class selrestr;
22 22
23 namespace generator { 23 namespace generator {
24 24
25 class generator { 25 class generator {
26 public: 26 public:
27 27
28 // Constructor 28 // Constructor
29 29
30 generator( 30 generator(
31 std::string verbNetPath, 31 std::string verbNetPath,
32 std::string agidPath, 32 std::string agidPath,
@@ -34,95 +34,95 @@ namespace verbly {
34 std::string cmudictPath, 34 std::string cmudictPath,
35 std::string imageNetPath, 35 std::string imageNetPath,
36 std::string outputPath); 36 std::string outputPath);
37 37
38 // Action 38 // Action
39 39
40 void run(); 40 void run();
41 41
42 private: 42 private:
43 43
44 // Subroutines 44 // Subroutines
45 45
46 void readWordNetSynsets(); 46 void readWordNetSynsets();
47 47
48 void readAdjectivePositioning(); 48 void readAdjectivePositioning();
49 49
50 void readImageNetUrls(); 50 void readImageNetUrls();
51 51
52 void readWordNetSenseKeys(); 52 void readWordNetSenseKeys();
53 53
54 void readVerbNet(); 54 void readVerbNet();
55 55
56 void readAgidInflections(); 56 void readAgidInflections();
57 57
58 void readPrepositions(); 58 void readPrepositions();
59 59
60 void readCmudictPronunciations(); 60 void readCmudictPronunciations();
61 61
62 void writeSchema(); 62 void writeSchema();
63 63
64 void dumpObjects(); 64 void dumpObjects();
65 65
66 void readWordNetAntonymy(); 66 void readWordNetAntonymy();
67 67
68 void readWordNetVariation(); 68 void readWordNetVariation();
69 69
70 void readWordNetClasses(); 70 void readWordNetClasses();
71 71
72 void readWordNetCausality(); 72 void readWordNetCausality();
73 73
74 void readWordNetEntailment(); 74 void readWordNetEntailment();
75 75
76 void readWordNetHypernymy(); 76 void readWordNetHypernymy();
77 77
78 void readWordNetInstantiation(); 78 void readWordNetInstantiation();
79 79
80 void readWordNetMemberMeronymy(); 80 void readWordNetMemberMeronymy();
81 81
82 void readWordNetPartMeronymy(); 82 void readWordNetPartMeronymy();
83 83
84 void readWordNetSubstanceMeronymy(); 84 void readWordNetSubstanceMeronymy();
85 85
86 void readWordNetPertainymy(); 86 void readWordNetPertainymy();
87 87
88 void readWordNetSpecification(); 88 void readWordNetSpecification();
89 89
90 void readWordNetSimilarity(); 90 void readWordNetSimilarity();
91 91
92 // Helpers 92 // Helpers
93 93
94 std::list<std::string> readFile(std::string path); 94 std::list<std::string> readFile(std::string path);
95 95
96 inline part_of_speech partOfSpeechByWnid(int wnid); 96 inline part_of_speech partOfSpeechByWnid(int wnid);
97 97
98 notion& createNotion(part_of_speech partOfSpeech); 98 notion& createNotion(part_of_speech partOfSpeech);
99 99
100 notion& lookupOrCreateNotion(int wnid); 100 notion& lookupOrCreateNotion(int wnid);
101 101
102 lemma& lookupOrCreateLemma(std::string base_form); 102 lemma& lookupOrCreateLemma(std::string base_form);
103 103
104 form& lookupOrCreateForm(std::string text); 104 form& lookupOrCreateForm(std::string text);
105 105
106 template <typename... Args> word& createWord(Args&&... args); 106 template <typename... Args> word& createWord(Args&&... args);
107 107
108 group& createGroup(xmlNodePtr top); 108 group& createGroup(xmlNodePtr top);
109 109
110 selrestr parseSelrestr(xmlNodePtr top); 110 selrestr parseSelrestr(xmlNodePtr top);
111 111
112 // Input 112 // Input
113 113
114 std::string verbNetPath_; 114 std::string verbNetPath_;
115 std::string agidPath_; 115 std::string agidPath_;
116 std::string wordNetPath_; 116 std::string wordNetPath_;
117 std::string cmudictPath_; 117 std::string cmudictPath_;
118 std::string imageNetPath_; 118 std::string imageNetPath_;
119 119
120 // Output 120 // Output
121 121
122 database db_; 122 database db_;
123 123
124 // Data 124 // Data
125 125
126 std::list<notion> notions_; 126 std::list<notion> notions_;
127 std::list<word> words_; 127 std::list<word> words_;
128 std::list<lemma> lemmas_; 128 std::list<lemma> lemmas_;
@@ -130,22 +130,22 @@ namespace verbly {
130 std::list<pronunciation> pronunciations_; 130 std::list<pronunciation> pronunciations_;
131 std::list<frame> frames_; 131 std::list<frame> frames_;
132 std::list<group> groups_; 132 std::list<group> groups_;
133 133
134 // Indexes 134 // Indexes
135 135
136 std::map<int, notion*> notionByWnid_; 136 std::map<int, notion*> notionByWnid_;
137 std::map<int, std::set<word*>> wordsByWnid_; 137 std::map<int, std::set<word*>> wordsByWnid_;
138 std::map<std::pair<int, int>, word*> wordByWnidAndWnum_; 138 std::map<std::pair<int, int>, word*> wordByWnidAndWnum_;
139 std::map<std::string, std::set<word*>> wordsByBaseForm_; 139 std::map<std::string, std::set<word*>> wordsByBaseForm_;
140 std::map<std::string, lemma*> lemmaByBaseForm_; 140 std::map<std::string, lemma*> lemmaByBaseForm_;
141 std::map<std::string, form*> formByText_; 141 std::map<std::string, form*> formByText_;
142 142
143 // Caches 143 // Caches
144 144
145 std::map<std::string, word*> wnSenseKeys_; 145 std::map<std::string, word*> wnSenseKeys_;
146 146
147 }; 147 };
148 148
149 }; 149 };
150}; 150};
151 151
diff --git a/generator/group.cpp b/generator/group.cpp index 334c2aa..cebe2b9 100644 --- a/generator/group.cpp +++ b/generator/group.cpp
@@ -8,37 +8,37 @@
8 8
9namespace verbly { 9namespace verbly {
10 namespace generator { 10 namespace generator {
11 11
12 int group::nextId_ = 0; 12 int group::nextId_ = 0;
13 13
14 group::group() : id_(nextId_++) 14 group::group() : id_(nextId_++)
15 { 15 {
16 } 16 }
17 17
18 void group::setParent(const group& parent) 18 void group::setParent(const group& parent)
19 { 19 {
20 // Adding a group to itself is nonsensical. 20 // Adding a group to itself is nonsensical.
21 assert(&parent != this); 21 assert(&parent != this);
22 22
23 parent_ = &parent; 23 parent_ = &parent;
24 } 24 }
25 25
26 void group::addRole(role r) 26 void group::addRole(role r)
27 { 27 {
28 std::string name = r.getName(); 28 std::string name = r.getName();
29 roles_[name] = std::move(r); 29 roles_[name] = std::move(r);
30 roleNames_.insert(std::move(name)); 30 roleNames_.insert(std::move(name));
31 } 31 }
32 32
33 void group::addFrame(const frame& f) 33 void group::addFrame(const frame& f)
34 { 34 {
35 frames_.insert(&f); 35 frames_.insert(&f);
36 } 36 }
37 37
38 std::set<std::string> group::getRoles() const 38 std::set<std::string> group::getRoles() const
39 { 39 {
40 std::set<std::string> fullRoles = roleNames_; 40 std::set<std::string> fullRoles = roleNames_;
41 41
42 if (hasParent()) 42 if (hasParent())
43 { 43 {
44 for (std::string name : getParent().getRoles()) 44 for (std::string name : getParent().getRoles())
@@ -46,10 +46,10 @@ namespace verbly {
46 fullRoles.insert(name); 46 fullRoles.insert(name);
47 } 47 }
48 } 48 }
49 49
50 return fullRoles; 50 return fullRoles;
51 } 51 }
52 52
53 const role& group::getRole(std::string name) const 53 const role& group::getRole(std::string name) const
54 { 54 {
55 if (roles_.count(name)) 55 if (roles_.count(name))
@@ -62,11 +62,11 @@ namespace verbly {
62 throw std::invalid_argument("Specified role not found in verb group"); 62 throw std::invalid_argument("Specified role not found in verb group");
63 } 63 }
64 } 64 }
65 65
66 std::set<const frame*> group::getFrames() const 66 std::set<const frame*> group::getFrames() const
67 { 67 {
68 std::set<const frame*> fullFrames = frames_; 68 std::set<const frame*> fullFrames = frames_;
69 69
70 if (hasParent()) 70 if (hasParent())
71 { 71 {
72 for (const frame* f : getParent().getFrames()) 72 for (const frame* f : getParent().getFrames())
@@ -74,47 +74,47 @@ namespace verbly {
74 fullFrames.insert(f); 74 fullFrames.insert(f);
75 } 75 }
76 } 76 }
77 77
78 return fullFrames; 78 return fullFrames;
79 } 79 }
80 80
81 database& operator<<(database& db, const group& arg) 81 database& operator<<(database& db, const group& arg)
82 { 82 {
83 // Serialize the group first 83 // Serialize the group first
84 { 84 {
85 std::list<field> fields; 85 std::list<field> fields;
86 fields.emplace_back("group_id", arg.getId()); 86 fields.emplace_back("group_id", arg.getId());
87 87
88 nlohmann::json jsonRoles; 88 nlohmann::json jsonRoles;
89 for (std::string name : arg.getRoles()) 89 for (std::string name : arg.getRoles())
90 { 90 {
91 const role& r = arg.getRole(name); 91 const role& r = arg.getRole(name);
92 92
93 nlohmann::json jsonRole; 93 nlohmann::json jsonRole;
94 jsonRole["type"] = name; 94 jsonRole["type"] = name;
95 jsonRole["selrestrs"] = r.getSelrestrs().toJson(); 95 jsonRole["selrestrs"] = r.getSelrestrs().toJson();
96 96
97 jsonRoles.emplace_back(std::move(jsonRole)); 97 jsonRoles.emplace_back(std::move(jsonRole));
98 } 98 }
99 99
100 fields.emplace_back("data", jsonRoles.dump()); 100 fields.emplace_back("data", jsonRoles.dump());
101 101
102 db.insertIntoTable("groups", std::move(fields)); 102 db.insertIntoTable("groups", std::move(fields));
103 } 103 }
104 104
105 // Then, serialize the group/frame relationship 105 // Then, serialize the group/frame relationship
106 for (const frame* f : arg.getFrames()) 106 for (const frame* f : arg.getFrames())
107 { 107 {
108 std::list<field> fields; 108 std::list<field> fields;
109 109
110 fields.emplace_back("group_id", arg.getId()); 110 fields.emplace_back("group_id", arg.getId());
111 fields.emplace_back("frame_id", f->getId()); 111 fields.emplace_back("frame_id", f->getId());
112 112
113 db.insertIntoTable("groups_frames", std::move(fields)); 113 db.insertIntoTable("groups_frames", std::move(fields));
114 } 114 }
115 115
116 return db; 116 return db;
117 } 117 }
118 118
119 }; 119 };
120}; 120};
diff --git a/generator/group.h b/generator/group.h index 5084ea4..83f40c2 100644 --- a/generator/group.h +++ b/generator/group.h
@@ -9,71 +9,71 @@
9 9
10namespace verbly { 10namespace verbly {
11 namespace generator { 11 namespace generator {
12 12
13 class frame; 13 class frame;
14 class database; 14 class database;
15 15
16 class group { 16 class group {
17 public: 17 public:
18 18
19 // Constructor 19 // Constructor
20 20
21 group(); 21 group();
22 22
23 // Mutators 23 // Mutators
24 24
25 void setParent(const group& parent); 25 void setParent(const group& parent);
26 26
27 void addRole(role r); 27 void addRole(role r);
28 28
29 void addFrame(const frame& f); 29 void addFrame(const frame& f);
30 30
31 // Accessors 31 // Accessors
32 32
33 int getId() const 33 int getId() const
34 { 34 {
35 return id_; 35 return id_;
36 } 36 }
37 37
38 bool hasParent() const 38 bool hasParent() const
39 { 39 {
40 return (parent_ != nullptr); 40 return (parent_ != nullptr);
41 } 41 }
42 42
43 const group& getParent() const 43 const group& getParent() const
44 { 44 {
45 // Calling code should always call hasParent first 45 // Calling code should always call hasParent first
46 assert(parent_ != nullptr); 46 assert(parent_ != nullptr);
47 47
48 return *parent_; 48 return *parent_;
49 } 49 }
50 50
51 std::set<std::string> getRoles() const; 51 std::set<std::string> getRoles() const;
52 52
53 const role& getRole(std::string name) const; 53 const role& getRole(std::string name) const;
54 54
55 std::set<const frame*> getFrames() const; 55 std::set<const frame*> getFrames() const;
56 56
57 private: 57 private:
58 58
59 static int nextId_; 59 static int nextId_;
60 60
61 const int id_; 61 const int id_;
62 62
63 const group* parent_ = nullptr; 63 const group* parent_ = nullptr;
64 std::map<std::string, role> roles_; 64 std::map<std::string, role> roles_;
65 std::set<const frame*> frames_; 65 std::set<const frame*> frames_;
66 66
67 // Caches 67 // Caches
68 68
69 std::set<std::string> roleNames_; 69 std::set<std::string> roleNames_;
70 70
71 }; 71 };
72 72
73 // Serializer 73 // Serializer
74 74
75 database& operator<<(database& db, const group& arg); 75 database& operator<<(database& db, const group& arg);
76 76
77 }; 77 };
78}; 78};
79 79
diff --git a/generator/main.cpp b/generator/main.cpp index 827c963..1b07706 100644 --- a/generator/main.cpp +++ b/generator/main.cpp
@@ -20,7 +20,7 @@ int main(int argc, char** argv)
20 try 20 try
21 { 21 {
22 verbly::generator::generator app(argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); 22 verbly::generator::generator app(argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
23 23
24 try 24 try
25 { 25 {
26 app.run(); 26 app.run();
diff --git a/generator/notion.cpp b/generator/notion.cpp index 290d982..1878ba9 100644 --- a/generator/notion.cpp +++ b/generator/notion.cpp
@@ -30,15 +30,15 @@ namespace verbly {
30 { 30 {
31 // Calling code should always call hasWnid and check that the notion is a noun first. 31 // Calling code should always call hasWnid and check that the notion is a noun first.
32 assert(hasWnid_ && (partOfSpeech_ == part_of_speech::noun)); 32 assert(hasWnid_ && (partOfSpeech_ == part_of_speech::noun));
33 33
34 numOfImages_++; 34 numOfImages_++;
35 } 35 }
36 36
37 void notion::setPrepositionGroups(std::list<std::string> groups) 37 void notion::setPrepositionGroups(std::list<std::string> groups)
38 { 38 {
39 // Calling code should always check that the notion is a preposition first. 39 // Calling code should always check that the notion is a preposition first.
40 assert(partOfSpeech_ == part_of_speech::preposition); 40 assert(partOfSpeech_ == part_of_speech::preposition);
41 41
42 prepositionGroups_ = groups; 42 prepositionGroups_ = groups;
43 } 43 }
44 44
@@ -54,7 +54,7 @@ namespace verbly {
54 if (arg.hasWnid()) 54 if (arg.hasWnid())
55 { 55 {
56 fields.emplace_back("wnid", arg.getWnid()); 56 fields.emplace_back("wnid", arg.getWnid());
57 57
58 if (arg.getPartOfSpeech() == part_of_speech::noun) 58 if (arg.getPartOfSpeech() == part_of_speech::noun)
59 { 59 {
60 fields.emplace_back("images", arg.getNumOfImages()); 60 fields.emplace_back("images", arg.getNumOfImages());
@@ -63,17 +63,17 @@ namespace verbly {
63 63
64 db.insertIntoTable("notions", std::move(fields)); 64 db.insertIntoTable("notions", std::move(fields));
65 } 65 }
66 66
67 // Next, serialize the is_a relationship if this is a preposition 67 // Next, serialize the is_a relationship if this is a preposition
68 if (arg.getPartOfSpeech() == part_of_speech::preposition) 68 if (arg.getPartOfSpeech() == part_of_speech::preposition)
69 { 69 {
70 for (std::string group : arg.getPrepositionGroups()) 70 for (std::string group : arg.getPrepositionGroups())
71 { 71 {
72 std::list<field> fields; 72 std::list<field> fields;
73 73
74 fields.emplace_back("notion_id", arg.getId()); 74 fields.emplace_back("notion_id", arg.getId());
75 fields.emplace_back("groupname", group); 75 fields.emplace_back("groupname", group);
76 76
77 db.insertIntoTable("is_a", std::move(fields)); 77 db.insertIntoTable("is_a", std::move(fields));
78 } 78 }
79 } 79 }
diff --git a/generator/notion.h b/generator/notion.h index cc64c48..6e38497 100644 --- a/generator/notion.h +++ b/generator/notion.h
@@ -23,7 +23,7 @@ namespace verbly {
23 // Mutators 23 // Mutators
24 24
25 void incrementNumOfImages(); 25 void incrementNumOfImages();
26 26
27 void setPrepositionGroups(std::list<std::string> groups); 27 void setPrepositionGroups(std::list<std::string> groups);
28 28
29 // Accessors 29 // Accessors
@@ -37,7 +37,7 @@ namespace verbly {
37 { 37 {
38 return partOfSpeech_; 38 return partOfSpeech_;
39 } 39 }
40 40
41 bool hasWnid() const 41 bool hasWnid() const
42 { 42 {
43 return hasWnid_; 43 return hasWnid_;
@@ -58,12 +58,12 @@ namespace verbly {
58 58
59 return numOfImages_; 59 return numOfImages_;
60 } 60 }
61 61
62 std::list<std::string> getPrepositionGroups() const 62 std::list<std::string> getPrepositionGroups() const
63 { 63 {
64 // Calling code should always check that the notion is a preposition first. 64 // Calling code should always check that the notion is a preposition first.
65 assert(partOfSpeech_ == part_of_speech::preposition); 65 assert(partOfSpeech_ == part_of_speech::preposition);
66 66
67 return prepositionGroups_; 67 return prepositionGroups_;
68 } 68 }
69 69
diff --git a/generator/part.cpp b/generator/part.cpp index b69ec65..8a75ed4 100644 --- a/generator/part.cpp +++ b/generator/part.cpp
@@ -3,56 +3,56 @@
3 3
4namespace verbly { 4namespace verbly {
5 namespace generator { 5 namespace generator {
6 6
7 part part::createNounPhrase(std::string role, selrestr selrestrs, std::set<std::string> synrestrs) 7 part part::createNounPhrase(std::string role, selrestr selrestrs, std::set<std::string> synrestrs)
8 { 8 {
9 part p(type::noun_phrase); 9 part p(type::noun_phrase);
10 10
11 new(&p.noun_phrase_.role) std::string(std::move(role)); 11 new(&p.noun_phrase_.role) std::string(std::move(role));
12 new(&p.noun_phrase_.selrestrs) selrestr(std::move(selrestrs)); 12 new(&p.noun_phrase_.selrestrs) selrestr(std::move(selrestrs));
13 new(&p.noun_phrase_.synrestrs) std::set<std::string>(std::move(synrestrs)); 13 new(&p.noun_phrase_.synrestrs) std::set<std::string>(std::move(synrestrs));
14 14
15 return p; 15 return p;
16 } 16 }
17 17
18 part part::createVerb() 18 part part::createVerb()
19 { 19 {
20 return part(type::verb); 20 return part(type::verb);
21 } 21 }
22 22
23 part part::createPreposition(std::set<std::string> choices, bool literal) 23 part part::createPreposition(std::set<std::string> choices, bool literal)
24 { 24 {
25 part p(type::preposition); 25 part p(type::preposition);
26 26
27 new(&p.preposition_.choices) std::set<std::string>(std::move(choices)); 27 new(&p.preposition_.choices) std::set<std::string>(std::move(choices));
28 p.preposition_.literal = literal; 28 p.preposition_.literal = literal;
29 29
30 return p; 30 return p;
31 } 31 }
32 32
33 part part::createAdjective() 33 part part::createAdjective()
34 { 34 {
35 return part(type::adjective); 35 return part(type::adjective);
36 } 36 }
37 37
38 part part::createAdverb() 38 part part::createAdverb()
39 { 39 {
40 return part(type::adverb); 40 return part(type::adverb);
41 } 41 }
42 42
43 part part::createLiteral(std::string value) 43 part part::createLiteral(std::string value)
44 { 44 {
45 part p(type::literal); 45 part p(type::literal);
46 46
47 new(&p.literal_) std::string(std::move(value)); 47 new(&p.literal_) std::string(std::move(value));
48 48
49 return p; 49 return p;
50 } 50 }
51 51
52 part::part(const part& other) 52 part::part(const part& other)
53 { 53 {
54 type_ = other.type_; 54 type_ = other.type_;
55 55
56 switch (type_) 56 switch (type_)
57 { 57 {
58 case type::noun_phrase: 58 case type::noun_phrase:
@@ -60,25 +60,25 @@ namespace verbly {
60 new(&noun_phrase_.role) std::string(other.noun_phrase_.role); 60 new(&noun_phrase_.role) std::string(other.noun_phrase_.role);
61 new(&noun_phrase_.selrestrs) selrestr(other.noun_phrase_.selrestrs); 61 new(&noun_phrase_.selrestrs) selrestr(other.noun_phrase_.selrestrs);
62 new(&noun_phrase_.synrestrs) std::set<std::string>(other.noun_phrase_.synrestrs); 62 new(&noun_phrase_.synrestrs) std::set<std::string>(other.noun_phrase_.synrestrs);
63 63
64 break; 64 break;
65 } 65 }
66 66
67 case type::preposition: 67 case type::preposition:
68 { 68 {
69 new(&preposition_.choices) std::set<std::string>(other.preposition_.choices); 69 new(&preposition_.choices) std::set<std::string>(other.preposition_.choices);
70 preposition_.literal = other.preposition_.literal; 70 preposition_.literal = other.preposition_.literal;
71 71
72 break; 72 break;
73 } 73 }
74 74
75 case type::literal: 75 case type::literal:
76 { 76 {
77 new(&literal_) std::string(other.literal_); 77 new(&literal_) std::string(other.literal_);
78 78
79 break; 79 break;
80 } 80 }
81 81
82 case type::verb: 82 case type::verb:
83 case type::adjective: 83 case type::adjective:
84 case type::adverb: 84 case type::adverb:
@@ -88,23 +88,23 @@ namespace verbly {
88 } 88 }
89 } 89 }
90 } 90 }
91 91
92 part::part(part&& other) : part() 92 part::part(part&& other) : part()
93 { 93 {
94 swap(*this, other); 94 swap(*this, other);
95 } 95 }
96 96
97 part& part::operator=(part other) 97 part& part::operator=(part other)
98 { 98 {
99 swap(*this, other); 99 swap(*this, other);
100 100
101 return *this; 101 return *this;
102 } 102 }
103 103
104 void swap(part& first, part& second) 104 void swap(part& first, part& second)
105 { 105 {
106 using type = part::type; 106 using type = part::type;
107 107
108 type tempType = first.type_; 108 type tempType = first.type_;
109 std::string tempRole; 109 std::string tempRole;
110 selrestr tempSelrestrs; 110 selrestr tempSelrestrs;
@@ -112,7 +112,7 @@ namespace verbly {
112 std::set<std::string> tempChoices; 112 std::set<std::string> tempChoices;
113 bool tempPrepLiteral; 113 bool tempPrepLiteral;
114 std::string tempLiteralValue; 114 std::string tempLiteralValue;
115 115
116 switch (tempType) 116 switch (tempType)
117 { 117 {
118 case type::noun_phrase: 118 case type::noun_phrase:
@@ -120,25 +120,25 @@ namespace verbly {
120 tempRole = std::move(first.noun_phrase_.role); 120 tempRole = std::move(first.noun_phrase_.role);
121 tempSelrestrs = std::move(first.noun_phrase_.selrestrs); 121 tempSelrestrs = std::move(first.noun_phrase_.selrestrs);
122 tempSynrestrs = std::move(first.noun_phrase_.synrestrs); 122 tempSynrestrs = std::move(first.noun_phrase_.synrestrs);
123 123
124 break; 124 break;
125 } 125 }
126 126
127 case type::preposition: 127 case type::preposition:
128 { 128 {
129 tempChoices = std::move(first.preposition_.choices); 129 tempChoices = std::move(first.preposition_.choices);
130 tempPrepLiteral = first.preposition_.literal; 130 tempPrepLiteral = first.preposition_.literal;
131 131
132 break; 132 break;
133 } 133 }
134 134
135 case type::literal: 135 case type::literal:
136 { 136 {
137 tempLiteralValue = std::move(first.literal_); 137 tempLiteralValue = std::move(first.literal_);
138 138
139 break; 139 break;
140 } 140 }
141 141
142 case type::verb: 142 case type::verb:
143 case type::adjective: 143 case type::adjective:
144 case type::adverb: 144 case type::adverb:
@@ -147,11 +147,11 @@ namespace verbly {
147 break; 147 break;
148 } 148 }
149 } 149 }
150 150
151 first.~part(); 151 first.~part();
152 152
153 first.type_ = second.type_; 153 first.type_ = second.type_;
154 154
155 switch (first.type_) 155 switch (first.type_)
156 { 156 {
157 case type::noun_phrase: 157 case type::noun_phrase:
@@ -159,25 +159,25 @@ namespace verbly {
159 new(&first.noun_phrase_.role) std::string(std::move(second.noun_phrase_.role)); 159 new(&first.noun_phrase_.role) std::string(std::move(second.noun_phrase_.role));
160 new(&first.noun_phrase_.selrestrs) selrestr(std::move(second.noun_phrase_.selrestrs)); 160 new(&first.noun_phrase_.selrestrs) selrestr(std::move(second.noun_phrase_.selrestrs));
161 new(&first.noun_phrase_.synrestrs) std::set<std::string>(std::move(second.noun_phrase_.synrestrs)); 161 new(&first.noun_phrase_.synrestrs) std::set<std::string>(std::move(second.noun_phrase_.synrestrs));
162 162
163 break; 163 break;
164 } 164 }
165 165
166 case type::preposition: 166 case type::preposition:
167 { 167 {
168 new(&first.preposition_.choices) std::set<std::string>(std::move(second.preposition_.choices)); 168 new(&first.preposition_.choices) std::set<std::string>(std::move(second.preposition_.choices));
169 first.preposition_.literal = second.preposition_.literal; 169 first.preposition_.literal = second.preposition_.literal;
170 170
171 break; 171 break;
172 } 172 }
173 173
174 case type::literal: 174 case type::literal:
175 { 175 {
176 new(&first.literal_) std::string(std::move(second.literal_)); 176 new(&first.literal_) std::string(std::move(second.literal_));
177 177
178 break; 178 break;
179 } 179 }
180 180
181 case type::verb: 181 case type::verb:
182 case type::adjective: 182 case type::adjective:
183 case type::adverb: 183 case type::adverb:
@@ -186,11 +186,11 @@ namespace verbly {
186 break; 186 break;
187 } 187 }
188 } 188 }
189 189
190 second.~part(); 190 second.~part();
191 191
192 second.type_ = tempType; 192 second.type_ = tempType;
193 193
194 switch (second.type_) 194 switch (second.type_)
195 { 195 {
196 case type::noun_phrase: 196 case type::noun_phrase:
@@ -198,25 +198,25 @@ namespace verbly {
198 new(&second.noun_phrase_.role) std::string(std::move(tempRole)); 198 new(&second.noun_phrase_.role) std::string(std::move(tempRole));
199 new(&second.noun_phrase_.selrestrs) selrestr(std::move(tempSelrestrs)); 199 new(&second.noun_phrase_.selrestrs) selrestr(std::move(tempSelrestrs));
200 new(&second.noun_phrase_.synrestrs) std::set<std::string>(std::move(tempSynrestrs)); 200 new(&second.noun_phrase_.synrestrs) std::set<std::string>(std::move(tempSynrestrs));
201 201
202 break; 202 break;
203 } 203 }
204 204
205 case type::preposition: 205 case type::preposition:
206 { 206 {
207 new(&second.preposition_.choices) std::set<std::string>(std::move(tempChoices)); 207 new(&second.preposition_.choices) std::set<std::string>(std::move(tempChoices));
208 second.preposition_.literal = tempPrepLiteral; 208 second.preposition_.literal = tempPrepLiteral;
209 209
210 break; 210 break;
211 } 211 }
212 212
213 case type::literal: 213 case type::literal:
214 { 214 {
215 new(&second.literal_) std::string(std::move(tempLiteralValue)); 215 new(&second.literal_) std::string(std::move(tempLiteralValue));
216 216
217 break; 217 break;
218 } 218 }
219 219
220 case type::verb: 220 case type::verb:
221 case type::adjective: 221 case type::adjective:
222 case type::adverb: 222 case type::adverb:
@@ -226,7 +226,7 @@ namespace verbly {
226 } 226 }
227 } 227 }
228 } 228 }
229 229
230 part::~part() 230 part::~part()
231 { 231 {
232 switch (type_) 232 switch (type_)
@@ -235,32 +235,32 @@ namespace verbly {
235 { 235 {
236 using string_type = std::string; 236 using string_type = std::string;
237 using set_type = std::set<std::string>; 237 using set_type = std::set<std::string>;
238 238
239 noun_phrase_.role.~string_type(); 239 noun_phrase_.role.~string_type();
240 noun_phrase_.selrestrs.~selrestr(); 240 noun_phrase_.selrestrs.~selrestr();
241 noun_phrase_.synrestrs.~set_type(); 241 noun_phrase_.synrestrs.~set_type();
242 242
243 break; 243 break;
244 } 244 }
245 245
246 case type::preposition: 246 case type::preposition:
247 { 247 {
248 using set_type = std::set<std::string>; 248 using set_type = std::set<std::string>;
249 249
250 preposition_.choices.~set_type(); 250 preposition_.choices.~set_type();
251 251
252 break; 252 break;
253 } 253 }
254 254
255 case type::literal: 255 case type::literal:
256 { 256 {
257 using string_type = std::string; 257 using string_type = std::string;
258 258
259 literal_.~string_type(); 259 literal_.~string_type();
260 260
261 break; 261 break;
262 } 262 }
263 263
264 case type::verb: 264 case type::verb:
265 case type::adjective: 265 case type::adjective:
266 case type::adverb: 266 case type::adverb:
@@ -270,7 +270,7 @@ namespace verbly {
270 } 270 }
271 } 271 }
272 } 272 }
273 273
274 std::string part::getNounRole() const 274 std::string part::getNounRole() const
275 { 275 {
276 if (type_ == type::noun_phrase) 276 if (type_ == type::noun_phrase)
@@ -280,7 +280,7 @@ namespace verbly {
280 throw std::domain_error("part::getNounRole is only valid for noun phrase parts"); 280 throw std::domain_error("part::getNounRole is only valid for noun phrase parts");
281 } 281 }
282 } 282 }
283 283
284 selrestr part::getNounSelrestrs() const 284 selrestr part::getNounSelrestrs() const
285 { 285 {
286 if (type_ == type::noun_phrase) 286 if (type_ == type::noun_phrase)
@@ -290,7 +290,7 @@ namespace verbly {
290 throw std::domain_error("part::getNounSelrestrs is only valid for noun phrase parts"); 290 throw std::domain_error("part::getNounSelrestrs is only valid for noun phrase parts");
291 } 291 }
292 } 292 }
293 293
294 std::set<std::string> part::getNounSynrestrs() const 294 std::set<std::string> part::getNounSynrestrs() const
295 { 295 {
296 if (type_ == type::noun_phrase) 296 if (type_ == type::noun_phrase)
@@ -300,7 +300,7 @@ namespace verbly {
300 throw std::domain_error("part::getNounSynrestrs is only valid for noun phrase parts"); 300 throw std::domain_error("part::getNounSynrestrs is only valid for noun phrase parts");
301 } 301 }
302 } 302 }
303 303
304 std::set<std::string> part::getPrepositionChoices() const 304 std::set<std::string> part::getPrepositionChoices() const
305 { 305 {
306 if (type_ == type::preposition) 306 if (type_ == type::preposition)
@@ -310,7 +310,7 @@ namespace verbly {
310 throw std::domain_error("part::getPrepositionChoices is only valid for preposition parts"); 310 throw std::domain_error("part::getPrepositionChoices is only valid for preposition parts");
311 } 311 }
312 } 312 }
313 313
314 bool part::isPrepositionLiteral() const 314 bool part::isPrepositionLiteral() const
315 { 315 {
316 if (type_ == type::preposition) 316 if (type_ == type::preposition)
@@ -320,7 +320,7 @@ namespace verbly {
320 throw std::domain_error("part::isPrepositionLiteral is only valid for preposition parts"); 320 throw std::domain_error("part::isPrepositionLiteral is only valid for preposition parts");
321 } 321 }
322 } 322 }
323 323
324 std::string part::getLiteralValue() const 324 std::string part::getLiteralValue() const
325 { 325 {
326 if (type_ == type::literal) 326 if (type_ == type::literal)
@@ -330,6 +330,6 @@ namespace verbly {
330 throw std::domain_error("part::getLiteralValue is only valid for literal parts"); 330 throw std::domain_error("part::getLiteralValue is only valid for literal parts");
331 } 331 }
332 } 332 }
333 333
334 }; 334 };
335}; 335};
diff --git a/generator/part.h b/generator/part.h index 86d5d57..b010f62 100644 --- a/generator/part.h +++ b/generator/part.h
@@ -7,7 +7,7 @@
7 7
8namespace verbly { 8namespace verbly {
9 namespace generator { 9 namespace generator {
10 10
11 class part { 11 class part {
12 public: 12 public:
13 enum class type { 13 enum class type {
@@ -19,78 +19,78 @@ namespace verbly {
19 adverb = 4, 19 adverb = 4,
20 literal = 5 20 literal = 5
21 }; 21 };
22 22
23 // Static factories 23 // Static factories
24 24
25 static part createNounPhrase(std::string role, selrestr selrestrs, std::set<std::string> synrestrs); 25 static part createNounPhrase(std::string role, selrestr selrestrs, std::set<std::string> synrestrs);
26 26
27 static part createVerb(); 27 static part createVerb();
28 28
29 static part createPreposition(std::set<std::string> choices, bool literal); 29 static part createPreposition(std::set<std::string> choices, bool literal);
30 30
31 static part createAdjective(); 31 static part createAdjective();
32 32
33 static part createAdverb(); 33 static part createAdverb();
34 34
35 static part createLiteral(std::string value); 35 static part createLiteral(std::string value);
36 36
37 // Copy and move constructors 37 // Copy and move constructors
38 38
39 part(const part& other); 39 part(const part& other);
40 40
41 part(part&& other); 41 part(part&& other);
42 42
43 // Assignment 43 // Assignment
44 44
45 part& operator=(part other); 45 part& operator=(part other);
46 46
47 // Swap 47 // Swap
48 48
49 friend void swap(part& first, part& second); 49 friend void swap(part& first, part& second);
50 50
51 // Destructor 51 // Destructor
52 52
53 ~part(); 53 ~part();
54 54
55 // General accessors 55 // General accessors
56 56
57 type getType() const 57 type getType() const
58 { 58 {
59 return type_; 59 return type_;
60 } 60 }
61 61
62 // Noun phrase accessors 62 // Noun phrase accessors
63 63
64 std::string getNounRole() const; 64 std::string getNounRole() const;
65 65
66 selrestr getNounSelrestrs() const; 66 selrestr getNounSelrestrs() const;
67 67
68 std::set<std::string> getNounSynrestrs() const; 68 std::set<std::string> getNounSynrestrs() const;
69 69
70 // Preposition accessors 70 // Preposition accessors
71 71
72 std::set<std::string> getPrepositionChoices() const; 72 std::set<std::string> getPrepositionChoices() const;
73 73
74 bool isPrepositionLiteral() const; 74 bool isPrepositionLiteral() const;
75 75
76 // Literal accessors 76 // Literal accessors
77 77
78 std::string getLiteralValue() const; 78 std::string getLiteralValue() const;
79 79
80 private: 80 private:
81 81
82 // Private constructors 82 // Private constructors
83 83
84 part() 84 part()
85 { 85 {
86 } 86 }
87 87
88 part(type t) : type_(t) 88 part(type t) : type_(t)
89 { 89 {
90 } 90 }
91 91
92 // Data 92 // Data
93 93
94 union { 94 union {
95 struct { 95 struct {
96 std::string role; 96 std::string role;
@@ -103,11 +103,11 @@ namespace verbly {
103 } preposition_; 103 } preposition_;
104 std::string literal_; 104 std::string literal_;
105 }; 105 };
106 106
107 type type_ = type::invalid; 107 type type_ = type::invalid;
108 108
109 }; 109 };
110 110
111 }; 111 };
112}; 112};
113 113
diff --git a/generator/progress.h b/generator/progress.h index fcb680d..76cde48 100644 --- a/generator/progress.h +++ b/generator/progress.h
@@ -5,20 +5,20 @@
5 5
6namespace verbly { 6namespace verbly {
7 namespace generator { 7 namespace generator {
8 8
9 class progress { 9 class progress {
10 private: 10 private:
11 std::string message; 11 std::string message;
12 int total; 12 int total;
13 int cur = 0; 13 int cur = 0;
14 int lprint = 0; 14 int lprint = 0;
15 15
16 public: 16 public:
17 progress(std::string message, int total) : message(message), total(total) 17 progress(std::string message, int total) : message(message), total(total)
18 { 18 {
19 std::cout << message << " 0%" << std::flush; 19 std::cout << message << " 0%" << std::flush;
20 } 20 }
21 21
22 void update(int val) 22 void update(int val)
23 { 23 {
24 if (val <= total) 24 if (val <= total)
@@ -27,29 +27,29 @@ namespace verbly {
27 } else { 27 } else {
28 cur = total; 28 cur = total;
29 } 29 }
30 30
31 int pp = cur * 100 / total; 31 int pp = cur * 100 / total;
32 if (pp != lprint) 32 if (pp != lprint)
33 { 33 {
34 lprint = pp; 34 lprint = pp;
35 35
36 std::cout << "\b\b\b\b" << std::right; 36 std::cout << "\b\b\b\b" << std::right;
37 std::cout.width(3); 37 std::cout.width(3);
38 std::cout << pp << "%" << std::flush; 38 std::cout << pp << "%" << std::flush;
39 } 39 }
40 } 40 }
41 41
42 void update() 42 void update()
43 { 43 {
44 update(cur+1); 44 update(cur+1);
45 } 45 }
46 46
47 ~progress() 47 ~progress()
48 { 48 {
49 std::cout << "\b\b\b\b100%" << std::endl; 49 std::cout << "\b\b\b\b100%" << std::endl;
50 } 50 }
51 }; 51 };
52 52
53 }; 53 };
54}; 54};
55 55
diff --git a/generator/word.cpp b/generator/word.cpp index 8ba3ce2..b3fc490 100644 --- a/generator/word.cpp +++ b/generator/word.cpp
@@ -37,7 +37,7 @@ namespace verbly {
37 { 37 {
38 adjectivePosition_ = adjectivePosition; 38 adjectivePosition_ = adjectivePosition;
39 } 39 }
40 40
41 void word::setVerbGroup(const group& verbGroup) 41 void word::setVerbGroup(const group& verbGroup)
42 { 42 {
43 verbGroup_ = &verbGroup; 43 verbGroup_ = &verbGroup;
@@ -46,7 +46,7 @@ namespace verbly {
46 database& operator<<(database& db, const word& arg) 46 database& operator<<(database& db, const word& arg)
47 { 47 {
48 std::list<field> fields; 48 std::list<field> fields;
49 49
50 fields.emplace_back("word_id", arg.getId()); 50 fields.emplace_back("word_id", arg.getId());
51 fields.emplace_back("notion_id", arg.getNotion().getId()); 51 fields.emplace_back("notion_id", arg.getNotion().getId());
52 fields.emplace_back("lemma_id", arg.getLemma().getId()); 52 fields.emplace_back("lemma_id", arg.getLemma().getId());
@@ -55,13 +55,13 @@ namespace verbly {
55 { 55 {
56 fields.emplace_back("tag_count", arg.getTagCount()); 56 fields.emplace_back("tag_count", arg.getTagCount());
57 } 57 }
58 58
59 if ((arg.getNotion().getPartOfSpeech() == part_of_speech::adjective) 59 if ((arg.getNotion().getPartOfSpeech() == part_of_speech::adjective)
60 && (arg.getAdjectivePosition() != positioning::undefined)) 60 && (arg.getAdjectivePosition() != positioning::undefined))
61 { 61 {
62 fields.emplace_back("position", static_cast<int>(arg.getAdjectivePosition())); 62 fields.emplace_back("position", static_cast<int>(arg.getAdjectivePosition()));
63 } 63 }
64 64
65 if ((arg.getNotion().getPartOfSpeech() == part_of_speech::verb) 65 if ((arg.getNotion().getPartOfSpeech() == part_of_speech::verb)
66 && (arg.hasVerbGroup())) 66 && (arg.hasVerbGroup()))
67 { 67 {
diff --git a/generator/word.h b/generator/word.h index 1d77ed3..a994ec3 100644 --- a/generator/word.h +++ b/generator/word.h
@@ -24,7 +24,7 @@ namespace verbly {
24 // Mutators 24 // Mutators
25 25
26 void setAdjectivePosition(positioning adjectivePosition); 26 void setAdjectivePosition(positioning adjectivePosition);
27 27
28 void setVerbGroup(const group& verbGroup); 28 void setVerbGroup(const group& verbGroup);
29 29
30 // Accessors 30 // Accessors
@@ -58,7 +58,7 @@ namespace verbly {
58 { 58 {
59 return hasTagCount_; 59 return hasTagCount_;
60 } 60 }
61 61
62 int getTagCount() const 62 int getTagCount() const
63 { 63 {
64 // Calling code should always call hasTagCount first. 64 // Calling code should always call hasTagCount first.
@@ -71,17 +71,17 @@ namespace verbly {
71 { 71 {
72 return adjectivePosition_; 72 return adjectivePosition_;
73 } 73 }
74 74
75 bool hasVerbGroup() const 75 bool hasVerbGroup() const
76 { 76 {
77 return (verbGroup_ != nullptr); 77 return (verbGroup_ != nullptr);
78 } 78 }
79 79
80 const group& getVerbGroup() const 80 const group& getVerbGroup() const
81 { 81 {
82 // Calling code should always call hasVerbGroup first. 82 // Calling code should always call hasVerbGroup first.
83 assert(verbGroup_ != nullptr); 83 assert(verbGroup_ != nullptr);
84 84
85 return *verbGroup_; 85 return *verbGroup_;
86 } 86 }
87 87
diff --git a/lib/binding.h b/lib/binding.h index 7fbe20e..5578a09 100644 --- a/lib/binding.h +++ b/lib/binding.h
@@ -12,9 +12,9 @@ namespace verbly {
12 integer, 12 integer,
13 string 13 string
14 }; 14 };
15 15
16 // Default constructor 16 // Default constructor
17 17
18 binding() 18 binding()
19 { 19 {
20 } 20 }
@@ -37,22 +37,22 @@ namespace verbly {
37 ~binding(); 37 ~binding();
38 38
39 // Generic accessors 39 // Generic accessors
40 40
41 type getType() const 41 type getType() const
42 { 42 {
43 return type_; 43 return type_;
44 } 44 }
45 45
46 // Integer 46 // Integer
47 47
48 binding(int arg); 48 binding(int arg);
49 49
50 int getInteger() const; 50 int getInteger() const;
51 51
52 // String 52 // String
53 53
54 binding(std::string arg); 54 binding(std::string arg);
55 55
56 std::string getString() const; 56 std::string getString() const;
57 57
58 private: 58 private:
diff --git a/lib/database.cpp b/lib/database.cpp index 351b93d..fb00ef3 100644 --- a/lib/database.cpp +++ b/lib/database.cpp
@@ -40,37 +40,37 @@ namespace verbly {
40 { 40 {
41 sqlite3_close_v2(ppdb_); 41 sqlite3_close_v2(ppdb_);
42 } 42 }
43 43
44 query<notion> database::notions(filter where, bool random, int limit) const 44 query<notion> database::notions(filter where, bool random, int limit) const
45 { 45 {
46 return query<notion>(*this, ppdb_, std::move(where), random, limit); 46 return query<notion>(*this, ppdb_, std::move(where), random, limit);
47 } 47 }
48 48
49 query<word> database::words(filter where, bool random, int limit) const 49 query<word> database::words(filter where, bool random, int limit) const
50 { 50 {
51 return query<word>(*this, ppdb_, std::move(where), random, limit); 51 return query<word>(*this, ppdb_, std::move(where), random, limit);
52 } 52 }
53 53
54 query<group> database::groups(filter where, bool random, int limit) const 54 query<group> database::groups(filter where, bool random, int limit) const
55 { 55 {
56 return query<group>(*this, ppdb_, std::move(where), random, limit); 56 return query<group>(*this, ppdb_, std::move(where), random, limit);
57 } 57 }
58 58
59 query<frame> database::frames(filter where, bool random, int limit) const 59 query<frame> database::frames(filter where, bool random, int limit) const
60 { 60 {
61 return query<frame>(*this, ppdb_, std::move(where), random, limit); 61 return query<frame>(*this, ppdb_, std::move(where), random, limit);
62 } 62 }
63 63
64 query<lemma> database::lemmas(filter where, bool random, int limit) const 64 query<lemma> database::lemmas(filter where, bool random, int limit) const
65 { 65 {
66 return query<lemma>(*this, ppdb_, std::move(where), random, limit); 66 return query<lemma>(*this, ppdb_, std::move(where), random, limit);
67 } 67 }
68 68
69 query<form> database::forms(filter where, bool random, int limit) const 69 query<form> database::forms(filter where, bool random, int limit) const
70 { 70 {
71 return query<form>(*this, ppdb_, std::move(where), random, limit); 71 return query<form>(*this, ppdb_, std::move(where), random, limit);
72 } 72 }
73 73
74 query<pronunciation> database::pronunciations(filter where, bool random, int limit) const 74 query<pronunciation> database::pronunciations(filter where, bool random, int limit) const
75 { 75 {
76 return query<pronunciation>(*this, ppdb_, std::move(where), random, limit); 76 return query<pronunciation>(*this, ppdb_, std::move(where), random, limit);
diff --git a/lib/database.h b/lib/database.h index d68c40b..ef50739 100644 --- a/lib/database.h +++ b/lib/database.h
@@ -15,7 +15,7 @@
15struct sqlite3; 15struct sqlite3;
16 16
17namespace verbly { 17namespace verbly {
18 18
19 template <typename Object> 19 template <typename Object>
20 class query; 20 class query;
21 21
@@ -43,21 +43,21 @@ namespace verbly {
43 // Destructor 43 // Destructor
44 44
45 ~database(); 45 ~database();
46 46
47 // Queries 47 // Queries
48 48
49 query<notion> notions(filter where, bool random = true, int limit = 1) const; 49 query<notion> notions(filter where, bool random = true, int limit = 1) const;
50 50
51 query<word> words(filter where, bool random = true, int limit = 1) const; 51 query<word> words(filter where, bool random = true, int limit = 1) const;
52 52
53 query<group> groups(filter where, bool random = true, int limit = 1) const; 53 query<group> groups(filter where, bool random = true, int limit = 1) const;
54 54
55 query<frame> frames(filter where, bool random = true, int limit = 1) const; 55 query<frame> frames(filter where, bool random = true, int limit = 1) const;
56 56
57 query<lemma> lemmas(filter where, bool random = true, int limit = 1) const; 57 query<lemma> lemmas(filter where, bool random = true, int limit = 1) const;
58 58
59 query<form> forms(filter where, bool random = true, int limit = 1) const; 59 query<form> forms(filter where, bool random = true, int limit = 1) const;
60 60
61 query<pronunciation> pronunciations(filter where, bool random = true, int limit = 1) const; 61 query<pronunciation> pronunciations(filter where, bool random = true, int limit = 1) const;
62 62
63 private: 63 private:
diff --git a/lib/enums.h b/lib/enums.h index b37be7b..e634959 100644 --- a/lib/enums.h +++ b/lib/enums.h
@@ -2,7 +2,7 @@
2#define ENUMS_H_260BA847 2#define ENUMS_H_260BA847
3 3
4namespace verbly { 4namespace verbly {
5 5
6 enum class part_of_speech { 6 enum class part_of_speech {
7 noun = 0, 7 noun = 0,
8 adjective = 1, 8 adjective = 1,
@@ -10,14 +10,14 @@ namespace verbly {
10 verb = 3, 10 verb = 3,
11 preposition = 4 11 preposition = 4
12 }; 12 };
13 13
14 enum class positioning { 14 enum class positioning {
15 undefined = -1, 15 undefined = -1,
16 predicate = 0, 16 predicate = 0,
17 attributive = 1, 17 attributive = 1,
18 postnominal = 2 18 postnominal = 2
19 }; 19 };
20 20
21 enum class inflection { 21 enum class inflection {
22 base = 0, 22 base = 0,
23 plural = 1, 23 plural = 1,
@@ -28,7 +28,7 @@ namespace verbly {
28 ing_form = 6, 28 ing_form = 6,
29 s_form = 7 29 s_form = 7
30 }; 30 };
31 31
32 enum class object { 32 enum class object {
33 undefined = -1, 33 undefined = -1,
34 notion = 0, 34 notion = 0,
@@ -39,7 +39,7 @@ namespace verbly {
39 form = 5, 39 form = 5,
40 pronunciation = 6 40 pronunciation = 6
41 }; 41 };
42 42
43}; 43};
44 44
45#endif /* end of include guard: ENUMS_H_260BA847 */ 45#endif /* end of include guard: ENUMS_H_260BA847 */
diff --git a/lib/field.cpp b/lib/field.cpp index 168935c..deecb06 100644 --- a/lib/field.cpp +++ b/lib/field.cpp
@@ -2,72 +2,72 @@
2#include "filter.h" 2#include "filter.h"
3 3
4namespace verbly { 4namespace verbly {
5 5
6 filter field::operator==(int value) const 6 filter field::operator==(int value) const
7 { 7 {
8 return filter(*this, filter::comparison::int_equals, value); 8 return filter(*this, filter::comparison::int_equals, value);
9 } 9 }
10 10
11 filter field::operator!=(int value) const 11 filter field::operator!=(int value) const
12 { 12 {
13 return filter(*this, filter::comparison::int_does_not_equal, value); 13 return filter(*this, filter::comparison::int_does_not_equal, value);
14 } 14 }
15 15
16 filter field::operator<(int value) const 16 filter field::operator<(int value) const
17 { 17 {
18 return filter(*this, filter::comparison::int_is_less_than, value); 18 return filter(*this, filter::comparison::int_is_less_than, value);
19 } 19 }
20 20
21 filter field::operator<=(int value) const 21 filter field::operator<=(int value) const
22 { 22 {
23 return filter(*this, filter::comparison::int_is_at_most, value); 23 return filter(*this, filter::comparison::int_is_at_most, value);
24 } 24 }
25 25
26 filter field::operator>(int value) const 26 filter field::operator>(int value) const
27 { 27 {
28 return filter(*this, filter::comparison::int_is_greater_than, value); 28 return filter(*this, filter::comparison::int_is_greater_than, value);
29 } 29 }
30 30
31 filter field::operator>=(int value) const 31 filter field::operator>=(int value) const
32 { 32 {
33 return filter(*this, filter::comparison::int_is_at_least, value); 33 return filter(*this, filter::comparison::int_is_at_least, value);
34 } 34 }
35 35
36 filter field::operator==(part_of_speech value) const 36 filter field::operator==(part_of_speech value) const
37 { 37 {
38 return filter(*this, filter::comparison::int_equals, static_cast<int>(value)); 38 return filter(*this, filter::comparison::int_equals, static_cast<int>(value));
39 } 39 }
40 40
41 filter field::operator==(positioning value) const 41 filter field::operator==(positioning value) const
42 { 42 {
43 return filter(*this, filter::comparison::int_equals, static_cast<int>(value)); 43 return filter(*this, filter::comparison::int_equals, static_cast<int>(value));
44 } 44 }
45 45
46 filter field::operator==(inflection value) const 46 filter field::operator==(inflection value) const
47 { 47 {
48 return filter(*this, filter::comparison::int_equals, static_cast<int>(value)); 48 return filter(*this, filter::comparison::int_equals, static_cast<int>(value));
49 } 49 }
50 50
51 filter field::operator==(bool value) const 51 filter field::operator==(bool value) const
52 { 52 {
53 return filter(*this, filter::comparison::boolean_equals, value); 53 return filter(*this, filter::comparison::boolean_equals, value);
54 } 54 }
55 55
56 filter field::operator==(std::string value) const 56 filter field::operator==(std::string value) const
57 { 57 {
58 return filter(*this, filter::comparison::string_equals, std::move(value)); 58 return filter(*this, filter::comparison::string_equals, std::move(value));
59 } 59 }
60 60
61 filter field::operator!=(std::string value) const 61 filter field::operator!=(std::string value) const
62 { 62 {
63 return filter(*this, filter::comparison::string_does_not_equal, std::move(value)); 63 return filter(*this, filter::comparison::string_does_not_equal, std::move(value));
64 } 64 }
65 65
66 filter field::operator%=(std::string value) const 66 filter field::operator%=(std::string value) const
67 { 67 {
68 return filter(*this, filter::comparison::string_is_like, std::move(value)); 68 return filter(*this, filter::comparison::string_is_like, std::move(value));
69 } 69 }
70 70
71 field::operator filter() const 71 field::operator filter() const
72 { 72 {
73 if (isJoin()) 73 if (isJoin())
@@ -77,7 +77,7 @@ namespace verbly {
77 return filter(*this, filter::comparison::is_not_null); 77 return filter(*this, filter::comparison::is_not_null);
78 } 78 }
79 } 79 }
80 80
81 filter field::operator!() const 81 filter field::operator!() const
82 { 82 {
83 if (isJoin()) 83 if (isJoin())
@@ -87,7 +87,7 @@ namespace verbly {
87 return filter(*this, filter::comparison::is_null); 87 return filter(*this, filter::comparison::is_null);
88 } 88 }
89 } 89 }
90 90
91 filter field::operator%=(filter joinCondition) const 91 filter field::operator%=(filter joinCondition) const
92 { 92 {
93 if (type_ == type::hierarchal_join) 93 if (type_ == type::hierarchal_join)
@@ -97,5 +97,5 @@ namespace verbly {
97 return filter(*this, filter::comparison::matches, std::move(joinCondition)); 97 return filter(*this, filter::comparison::matches, std::move(joinCondition));
98 } 98 }
99 } 99 }
100 100
101}; 101};
diff --git a/lib/lemma.cpp b/lib/lemma.cpp index 7fdc360..1601460 100644 --- a/lib/lemma.cpp +++ b/lib/lemma.cpp
@@ -4,71 +4,71 @@
4#include "query.h" 4#include "query.h"
5 5
6namespace verbly { 6namespace verbly {
7 7
8 const object lemma::objectType = object::lemma; 8 const object lemma::objectType = object::lemma;
9 9
10 const std::list<std::string> lemma::select = {"lemma_id"}; 10 const std::list<std::string> lemma::select = {"lemma_id"};
11 11
12 const field lemma::id = field::integerField(object::lemma, "lemma_id"); 12 const field lemma::id = field::integerField(object::lemma, "lemma_id");
13 13
14 const field lemma::word = field::joinField(object::lemma, "lemma_id", object::word); 14 const field lemma::word = field::joinField(object::lemma, "lemma_id", object::word);
15 15
16 const field lemma::formJoin = field::joinField(object::lemma, "form_id", object::form); 16 const field lemma::formJoin = field::joinField(object::lemma, "form_id", object::form);
17 const field lemma::inflectionCategory = field::integerField(object::lemma, "category"); 17 const field lemma::inflectionCategory = field::integerField(object::lemma, "category");
18 18
19 filter operator%=(lemma::inflection_field check, filter joinCondition) 19 filter operator%=(lemma::inflection_field check, filter joinCondition)
20 { 20 {
21 return (lemma::formJoin %= joinCondition) && (lemma::inflectionCategory == check.getCategory()); 21 return (lemma::formJoin %= joinCondition) && (lemma::inflectionCategory == check.getCategory());
22 } 22 }
23 23
24 lemma::inflection_field::operator filter() const 24 lemma::inflection_field::operator filter() const
25 { 25 {
26 return (lemma::inflectionCategory == category_); 26 return (lemma::inflectionCategory == category_);
27 } 27 }
28 28
29 lemma::lemma(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) 29 lemma::lemma(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true)
30 { 30 {
31 id_ = sqlite3_column_int(row, 0); 31 id_ = sqlite3_column_int(row, 0);
32 } 32 }
33 33
34 const form& lemma::getBaseForm() const 34 const form& lemma::getBaseForm() const
35 { 35 {
36 if (!valid_) 36 if (!valid_)
37 { 37 {
38 throw std::domain_error("Bad access to uninitialized lemma"); 38 throw std::domain_error("Bad access to uninitialized lemma");
39 } 39 }
40 40
41 if (!forms_.count(inflection::base)) 41 if (!forms_.count(inflection::base))
42 { 42 {
43 initializeForm(inflection::base); 43 initializeForm(inflection::base);
44 } 44 }
45 45
46 return forms_.at(inflection::base).front(); 46 return forms_.at(inflection::base).front();
47 } 47 }
48 48
49 bool lemma::hasInflection(inflection category) const 49 bool lemma::hasInflection(inflection category) const
50 { 50 {
51 return !getInflections(category).empty(); 51 return !getInflections(category).empty();
52 } 52 }
53 53
54 const std::vector<form>& lemma::getInflections(inflection category) const 54 const std::vector<form>& lemma::getInflections(inflection category) const
55 { 55 {
56 if (!valid_) 56 if (!valid_)
57 { 57 {
58 throw std::domain_error("Bad access to uninitialized lemma"); 58 throw std::domain_error("Bad access to uninitialized lemma");
59 } 59 }
60 60
61 if (!forms_.count(category)) 61 if (!forms_.count(category))
62 { 62 {
63 initializeForm(category); 63 initializeForm(category);
64 } 64 }
65 65
66 return forms_.at(category); 66 return forms_.at(category);
67 } 67 }
68 68
69 void lemma::initializeForm(inflection infl) const 69 void lemma::initializeForm(inflection infl) const
70 { 70 {
71 forms_[infl] = db_->forms(form::lemma(infl) %= *this, false, -1).all(); 71 forms_[infl] = db_->forms(form::lemma(infl) %= *this, false, -1).all();
72 } 72 }
73 73
74}; 74};
diff --git a/lib/lemma.h b/lib/lemma.h index 8c8d1c1..407fa3c 100644 --- a/lib/lemma.h +++ b/lib/lemma.h
@@ -13,110 +13,110 @@
13struct sqlite3_stmt; 13struct sqlite3_stmt;
14 14
15namespace verbly { 15namespace verbly {
16 16
17 class database; 17 class database;
18 18
19 class lemma { 19 class lemma {
20 public: 20 public:
21 21
22 // Default constructor 22 // Default constructor
23 23
24 lemma() = default; 24 lemma() = default;
25 25
26 // Construct from database 26 // Construct from database
27 27
28 lemma(const database& db, sqlite3_stmt* row); 28 lemma(const database& db, sqlite3_stmt* row);
29 29
30 // Accessors 30 // Accessors
31 31
32 operator bool() const 32 operator bool() const
33 { 33 {
34 return valid_; 34 return valid_;
35 } 35 }
36 36
37 int getId() const 37 int getId() const
38 { 38 {
39 if (!valid_) 39 if (!valid_)
40 { 40 {
41 throw std::domain_error("Bad access to uninitialized lemma"); 41 throw std::domain_error("Bad access to uninitialized lemma");
42 } 42 }
43 43
44 return id_; 44 return id_;
45 } 45 }
46 46
47 const form& getBaseForm() const; 47 const form& getBaseForm() const;
48 48
49 bool hasInflection(inflection category) const; 49 bool hasInflection(inflection category) const;
50 50
51 const std::vector<form>& getInflections(inflection category) const; 51 const std::vector<form>& getInflections(inflection category) const;
52 52
53 // Type info 53 // Type info
54 54
55 static const object objectType; 55 static const object objectType;
56 56
57 static const std::list<std::string> select; 57 static const std::list<std::string> select;
58 58
59 // Query fields 59 // Query fields
60 60
61 static const field id; 61 static const field id;
62 62
63 operator filter() const 63 operator filter() const
64 { 64 {
65 if (!valid_) 65 if (!valid_)
66 { 66 {
67 throw std::domain_error("Bad access to uninitialized lemma"); 67 throw std::domain_error("Bad access to uninitialized lemma");
68 } 68 }
69 69
70 return (id == id_); 70 return (id == id_);
71 } 71 }
72 72
73 // Relationships to other objects 73 // Relationships to other objects
74 74
75 static const field word; 75 static const field word;
76 76
77 class inflection_field { 77 class inflection_field {
78 public: 78 public:
79 79
80 inflection_field(inflection category) : category_(category) 80 inflection_field(inflection category) : category_(category)
81 { 81 {
82 } 82 }
83 83
84 const inflection getCategory() const 84 const inflection getCategory() const
85 { 85 {
86 return category_; 86 return category_;
87 } 87 }
88 88
89 operator filter() const; 89 operator filter() const;
90 90
91 private: 91 private:
92 92
93 const inflection category_; 93 const inflection category_;
94 }; 94 };
95 95
96 static const inflection_field form(inflection category) 96 static const inflection_field form(inflection category)
97 { 97 {
98 return inflection_field(category); 98 return inflection_field(category);
99 } 99 }
100 100
101 friend filter operator%=(lemma::inflection_field check, filter joinCondition); 101 friend filter operator%=(lemma::inflection_field check, filter joinCondition);
102 102
103 private: 103 private:
104 104
105 void initializeForm(inflection category) const; 105 void initializeForm(inflection category) const;
106 106
107 bool valid_ = false; 107 bool valid_ = false;
108 108
109 int id_; 109 int id_;
110 110
111 mutable std::map<inflection, std::vector<class form>> forms_; 111 mutable std::map<inflection, std::vector<class form>> forms_;
112 112
113 const database* db_; 113 const database* db_;
114 114
115 static const field formJoin; 115 static const field formJoin;
116 static const field inflectionCategory; 116 static const field inflectionCategory;
117 117
118 }; 118 };
119 119
120}; 120};
121 121
122#endif /* end of include guard: LEMMA_H_0A180D30 */ 122#endif /* end of include guard: LEMMA_H_0A180D30 */
diff --git a/lib/pronunciation.cpp b/lib/pronunciation.cpp index f5b742f..e937ba6 100644 --- a/lib/pronunciation.cpp +++ b/lib/pronunciation.cpp
@@ -6,64 +6,64 @@
6#include "util.h" 6#include "util.h"
7 7
8namespace verbly { 8namespace verbly {
9 9
10 const object pronunciation::objectType = object::pronunciation; 10 const object pronunciation::objectType = object::pronunciation;
11 11
12 const std::list<std::string> pronunciation::select = {"pronunciation_id", "phonemes", "syllables", "stress", "prerhyme", "rhyme"}; 12 const std::list<std::string> pronunciation::select = {"pronunciation_id", "phonemes", "syllables", "stress", "prerhyme", "rhyme"};
13 13
14 const field pronunciation::id = field::integerField(object::pronunciation, "pronunciation_id"); 14 const field pronunciation::id = field::integerField(object::pronunciation, "pronunciation_id");
15 const field pronunciation::numOfSyllables = field::integerField(object::pronunciation, "syllables"); 15 const field pronunciation::numOfSyllables = field::integerField(object::pronunciation, "syllables");
16 const field pronunciation::stress = field::stringField(object::pronunciation, "stress"); 16 const field pronunciation::stress = field::stringField(object::pronunciation, "stress");
17 17
18 const field pronunciation::form = field::joinThrough(object::pronunciation, "pronunciation_id", object::form, "forms_pronunciations", "form_id"); 18 const field pronunciation::form = field::joinThrough(object::pronunciation, "pronunciation_id", object::form, "forms_pronunciations", "form_id");
19 19
20 const field pronunciation::prerhyme = field::stringField(object::pronunciation, "prerhyme", true); 20 const field pronunciation::prerhyme = field::stringField(object::pronunciation, "prerhyme", true);
21 const field pronunciation::rhyme = field::stringField(object::pronunciation, "rhyme", true); 21 const field pronunciation::rhyme = field::stringField(object::pronunciation, "rhyme", true);
22 22
23 pronunciation::pronunciation(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) 23 pronunciation::pronunciation(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true)
24 { 24 {
25 id_ = sqlite3_column_int(row, 0); 25 id_ = sqlite3_column_int(row, 0);
26 26
27 std::string phonemesStr(reinterpret_cast<const char*>(sqlite3_column_text(row, 1))); 27 std::string phonemesStr(reinterpret_cast<const char*>(sqlite3_column_text(row, 1)));
28 phonemes_ = split<std::vector<std::string>>(phonemesStr, " "); 28 phonemes_ = split<std::vector<std::string>>(phonemesStr, " ");
29 29
30 syllables_ = sqlite3_column_int(row, 2); 30 syllables_ = sqlite3_column_int(row, 2);
31 stress_ = std::string(reinterpret_cast<const char*>(sqlite3_column_text(row, 3))); 31 stress_ = std::string(reinterpret_cast<const char*>(sqlite3_column_text(row, 3)));
32 32
33 if (sqlite3_column_type(row, 5) != SQLITE_NULL) 33 if (sqlite3_column_type(row, 5) != SQLITE_NULL)
34 { 34 {
35 hasRhyme_ = true; 35 hasRhyme_ = true;
36 36
37 prerhyme_ = std::string(reinterpret_cast<const char*>(sqlite3_column_text(row, 4))); 37 prerhyme_ = std::string(reinterpret_cast<const char*>(sqlite3_column_text(row, 4)));
38 rhyme_ = std::string(reinterpret_cast<const char*>(sqlite3_column_text(row, 5))); 38 rhyme_ = std::string(reinterpret_cast<const char*>(sqlite3_column_text(row, 5)));
39 } 39 }
40 } 40 }
41 41
42 filter pronunciation::rhymesWith(const pronunciation& arg) 42 filter pronunciation::rhymesWith(const pronunciation& arg)
43 { 43 {
44 return (prerhyme != arg.getPrerhyme()) && (rhyme == arg.getRhyme()); 44 return (prerhyme != arg.getPrerhyme()) && (rhyme == arg.getRhyme());
45 } 45 }
46 46
47 /*filter pronunciation::rhymesWith(const class form& arg) 47 /*filter pronunciation::rhymesWith(const class form& arg)
48 { 48 {
49 filter result; 49 filter result;
50 50
51 for (const pronunciation& p : arg.getPronunciations()) 51 for (const pronunciation& p : arg.getPronunciations())
52 { 52 {
53 result |= rhymesWith(p); 53 result |= rhymesWith(p);
54 } 54 }
55 55
56 return result; 56 return result;
57 } 57 }
58 58
59 filter pronunciation::rhymesWith(const lemma& arg) 59 filter pronunciation::rhymesWith(const lemma& arg)
60 { 60 {
61 return rhymesWith(arg.getBaseForm()); 61 return rhymesWith(arg.getBaseForm());
62 } 62 }
63 63
64 filter pronunciation::rhymesWith(const word& arg) 64 filter pronunciation::rhymesWith(const word& arg)
65 { 65 {
66 return rhymesWith(arg.getLemma()); 66 return rhymesWith(arg.getLemma());
67 }*/ 67 }*/
68 68
69}; 69};
diff --git a/lib/query.h b/lib/query.h index e31be3d..352748f 100644 --- a/lib/query.h +++ b/lib/query.h
@@ -11,36 +11,36 @@
11#include "binding.h" 11#include "binding.h"
12 12
13namespace verbly { 13namespace verbly {
14 14
15 class database_error : public std::logic_error { 15 class database_error : public std::logic_error {
16 public: 16 public:
17 17
18 database_error(std::string msg, std::string sqlMsg) : std::logic_error(msg + " (" + sqlMsg + ")") 18 database_error(std::string msg, std::string sqlMsg) : std::logic_error(msg + " (" + sqlMsg + ")")
19 { 19 {
20 } 20 }
21 }; 21 };
22 22
23 template <typename Object> 23 template <typename Object>
24 class query { 24 class query {
25 public: 25 public:
26 26
27 query(const database& db, sqlite3* ppdb, filter queryFilter, bool random, int limit) : db_(&db) 27 query(const database& db, sqlite3* ppdb, filter queryFilter, bool random, int limit) : db_(&db)
28 { 28 {
29 statement stmt(Object::objectType, std::move(queryFilter)); 29 statement stmt(Object::objectType, std::move(queryFilter));
30 30
31 std::string queryString = stmt.getQueryString(Object::select, random, limit); 31 std::string queryString = stmt.getQueryString(Object::select, random, limit);
32 std::list<binding> bindings = stmt.getBindings(); 32 std::list<binding> bindings = stmt.getBindings();
33 33
34 std::cout << queryString << std::endl; 34 std::cout << queryString << std::endl;
35 35
36 if (sqlite3_prepare_v2(ppdb, queryString.c_str(), queryString.length(), &ppstmt_, NULL) != SQLITE_OK) 36 if (sqlite3_prepare_v2(ppdb, queryString.c_str(), queryString.length(), &ppstmt_, NULL) != SQLITE_OK)
37 { 37 {
38 std::string errorMsg = sqlite3_errmsg(ppdb); 38 std::string errorMsg = sqlite3_errmsg(ppdb);
39 sqlite3_finalize(ppstmt_); 39 sqlite3_finalize(ppstmt_);
40 40
41 throw database_error("Error preparing query", errorMsg); 41 throw database_error("Error preparing query", errorMsg);
42 } 42 }
43 43
44 int i = 1; 44 int i = 1;
45 for (const binding& value : bindings) 45 for (const binding& value : bindings)
46 { 46 {
@@ -52,52 +52,52 @@ namespace verbly {
52 { 52 {
53 std::string errorMsg = sqlite3_errmsg(ppdb); 53 std::string errorMsg = sqlite3_errmsg(ppdb);
54 sqlite3_finalize(ppstmt_); 54 sqlite3_finalize(ppstmt_);
55 55
56 throw database_error("Error binding value to query", errorMsg); 56 throw database_error("Error binding value to query", errorMsg);
57 } 57 }
58 58
59 break; 59 break;
60 } 60 }
61 61
62 case binding::type::string: 62 case binding::type::string:
63 { 63 {
64 if (sqlite3_bind_text(ppstmt_, i, value.getString().c_str(), value.getString().length(), SQLITE_TRANSIENT) != SQLITE_OK) 64 if (sqlite3_bind_text(ppstmt_, i, value.getString().c_str(), value.getString().length(), SQLITE_TRANSIENT) != SQLITE_OK)
65 { 65 {
66 std::string errorMsg = sqlite3_errmsg(ppdb); 66 std::string errorMsg = sqlite3_errmsg(ppdb);
67 sqlite3_finalize(ppstmt_); 67 sqlite3_finalize(ppstmt_);
68 68
69 throw database_error("Error binding value to query", errorMsg); 69 throw database_error("Error binding value to query", errorMsg);
70 } 70 }
71 71
72 break; 72 break;
73 } 73 }
74 74
75 case binding::type::invalid: 75 case binding::type::invalid:
76 { 76 {
77 throw std::logic_error("Cannot use invalid bindings"); 77 throw std::logic_error("Cannot use invalid bindings");
78 } 78 }
79 } 79 }
80 80
81 i++; 81 i++;
82 } 82 }
83 } 83 }
84 84
85 ~query() 85 ~query()
86 { 86 {
87 sqlite3_finalize(ppstmt_); 87 sqlite3_finalize(ppstmt_);
88 } 88 }
89 89
90 std::vector<Object> all() const 90 std::vector<Object> all() const
91 { 91 {
92 std::vector<Object> result; 92 std::vector<Object> result;
93 93
94 while (sqlite3_step(ppstmt_) == SQLITE_ROW) 94 while (sqlite3_step(ppstmt_) == SQLITE_ROW)
95 { 95 {
96 result.emplace_back(*db_, ppstmt_); 96 result.emplace_back(*db_, ppstmt_);
97 } 97 }
98 98
99 sqlite3_reset(ppstmt_); 99 sqlite3_reset(ppstmt_);
100 100
101 return result; 101 return result;
102 } 102 }
103 103
@@ -111,13 +111,13 @@ namespace verbly {
111 throw std::logic_error("query returned empty dataset"); 111 throw std::logic_error("query returned empty dataset");
112 } 112 }
113 } 113 }
114 114
115 private: 115 private:
116 const database* db_; 116 const database* db_;
117 sqlite3_stmt* ppstmt_; 117 sqlite3_stmt* ppstmt_;
118 118
119 }; 119 };
120 120
121}; 121};
122 122
123#endif /* end of include guard: QUERY_H_7CC5284C */ 123#endif /* end of include guard: QUERY_H_7CC5284C */
diff --git a/lib/role.h b/lib/role.h index 8653710..4884ef3 100644 --- a/lib/role.h +++ b/lib/role.h
@@ -9,13 +9,13 @@ namespace verbly {
9 9
10 class role { 10 class role {
11 public: 11 public:
12 12
13 // Default constructor 13 // Default constructor
14 14
15 role() = default; 15 role() = default;
16 16
17 // Constructor 17 // Constructor
18 18
19 role( 19 role(
20 std::string name, 20 std::string name,
21 selrestr selrestrs = {}) : 21 selrestr selrestrs = {}) :
@@ -24,35 +24,35 @@ namespace verbly {
24 selrestrs_(selrestrs) 24 selrestrs_(selrestrs)
25 { 25 {
26 } 26 }
27 27
28 // Accessors 28 // Accessors
29 29
30 const std::string& getName() const 30 const std::string& getName() const
31 { 31 {
32 if (!valid_) 32 if (!valid_)
33 { 33 {
34 throw std::domain_error("Bad access to invalid role"); 34 throw std::domain_error("Bad access to invalid role");
35 } 35 }
36 36
37 return name_; 37 return name_;
38 } 38 }
39 39
40 const selrestr& getSelrestrs() const 40 const selrestr& getSelrestrs() const
41 { 41 {
42 if (!valid_) 42 if (!valid_)
43 { 43 {
44 throw std::domain_error("Bad access to invalid role"); 44 throw std::domain_error("Bad access to invalid role");
45 } 45 }
46 46
47 return selrestrs_; 47 return selrestrs_;
48 } 48 }
49 49
50 private: 50 private:
51 51
52 bool valid_ = false; 52 bool valid_ = false;
53 std::string name_; 53 std::string name_;
54 selrestr selrestrs_; 54 selrestr selrestrs_;
55 55
56 }; 56 };
57 57
58}; 58};
diff --git a/lib/selrestr.cpp b/lib/selrestr.cpp index 74ea726..8646871 100644 --- a/lib/selrestr.cpp +++ b/lib/selrestr.cpp
@@ -1,7 +1,7 @@
1#include "selrestr.h" 1#include "selrestr.h"
2 2
3namespace verbly { 3namespace verbly {
4 4
5 selrestr::selrestr(nlohmann::json data) 5 selrestr::selrestr(nlohmann::json data)
6 { 6 {
7 if (data.find("children") != data.end()) 7 if (data.find("children") != data.end())
@@ -13,7 +13,7 @@ namespace verbly {
13 { 13 {
14 group_.children.emplace_back(child); 14 group_.children.emplace_back(child);
15 } 15 }
16 16
17 group_.orlogic = (data["logic"] == "or"); 17 group_.orlogic = (data["logic"] == "or");
18 } else if (data.find("type") != data.end()) 18 } else if (data.find("type") != data.end())
19 { 19 {
@@ -24,139 +24,139 @@ namespace verbly {
24 type_ = type::empty; 24 type_ = type::empty;
25 } 25 }
26 } 26 }
27 27
28 selrestr::selrestr(const selrestr& other) 28 selrestr::selrestr(const selrestr& other)
29 { 29 {
30 type_ = other.type_; 30 type_ = other.type_;
31 31
32 switch (type_) 32 switch (type_)
33 { 33 {
34 case type::singleton: 34 case type::singleton:
35 { 35 {
36 singleton_.pos = other.singleton_.pos; 36 singleton_.pos = other.singleton_.pos;
37 new(&singleton_.restriction) std::string(other.singleton_.restriction); 37 new(&singleton_.restriction) std::string(other.singleton_.restriction);
38 38
39 break; 39 break;
40 } 40 }
41 41
42 case type::group: 42 case type::group:
43 { 43 {
44 new(&group_.children) std::list<selrestr>(other.group_.children); 44 new(&group_.children) std::list<selrestr>(other.group_.children);
45 group_.orlogic = other.group_.orlogic; 45 group_.orlogic = other.group_.orlogic;
46 46
47 break; 47 break;
48 } 48 }
49 49
50 case type::empty: 50 case type::empty:
51 { 51 {
52 break; 52 break;
53 } 53 }
54 } 54 }
55 } 55 }
56 56
57 selrestr::selrestr(selrestr&& other) : selrestr() 57 selrestr::selrestr(selrestr&& other) : selrestr()
58 { 58 {
59 swap(*this, other); 59 swap(*this, other);
60 } 60 }
61 61
62 selrestr& selrestr::operator=(selrestr other) 62 selrestr& selrestr::operator=(selrestr other)
63 { 63 {
64 swap(*this, other); 64 swap(*this, other);
65 65
66 return *this; 66 return *this;
67 } 67 }
68 68
69 void swap(selrestr& first, selrestr& second) 69 void swap(selrestr& first, selrestr& second)
70 { 70 {
71 using type = selrestr::type; 71 using type = selrestr::type;
72 72
73 type tempType = first.type_; 73 type tempType = first.type_;
74 int tempPos; 74 int tempPos;
75 std::string tempRestriction; 75 std::string tempRestriction;
76 std::list<selrestr> tempChildren; 76 std::list<selrestr> tempChildren;
77 bool tempOrlogic; 77 bool tempOrlogic;
78 78
79 switch (tempType) 79 switch (tempType)
80 { 80 {
81 case type::singleton: 81 case type::singleton:
82 { 82 {
83 tempPos = first.singleton_.pos; 83 tempPos = first.singleton_.pos;
84 tempRestriction = std::move(first.singleton_.restriction); 84 tempRestriction = std::move(first.singleton_.restriction);
85 85
86 break; 86 break;
87 } 87 }
88 88
89 case type::group: 89 case type::group:
90 { 90 {
91 tempChildren = std::move(first.group_.children); 91 tempChildren = std::move(first.group_.children);
92 tempOrlogic = first.group_.orlogic; 92 tempOrlogic = first.group_.orlogic;
93 93
94 break; 94 break;
95 } 95 }
96 96
97 case type::empty: 97 case type::empty:
98 { 98 {
99 break; 99 break;
100 } 100 }
101 } 101 }
102 102
103 first.~selrestr(); 103 first.~selrestr();
104 104
105 first.type_ = second.type_; 105 first.type_ = second.type_;
106 106
107 switch (first.type_) 107 switch (first.type_)
108 { 108 {
109 case type::singleton: 109 case type::singleton:
110 { 110 {
111 first.singleton_.pos = second.singleton_.pos; 111 first.singleton_.pos = second.singleton_.pos;
112 new(&first.singleton_.restriction) std::string(std::move(second.singleton_.restriction)); 112 new(&first.singleton_.restriction) std::string(std::move(second.singleton_.restriction));
113 113
114 break; 114 break;
115 } 115 }
116 116
117 case type::group: 117 case type::group:
118 { 118 {
119 new(&first.group_.children) std::list<selrestr>(std::move(second.group_.children)); 119 new(&first.group_.children) std::list<selrestr>(std::move(second.group_.children));
120 first.group_.orlogic = second.group_.orlogic; 120 first.group_.orlogic = second.group_.orlogic;
121 121
122 break; 122 break;
123 } 123 }
124 124
125 case type::empty: 125 case type::empty:
126 { 126 {
127 break; 127 break;
128 } 128 }
129 } 129 }
130 130
131 second.~selrestr(); 131 second.~selrestr();
132 132
133 second.type_ = tempType; 133 second.type_ = tempType;
134 134
135 switch (second.type_) 135 switch (second.type_)
136 { 136 {
137 case type::singleton: 137 case type::singleton:
138 { 138 {
139 second.singleton_.pos = tempPos; 139 second.singleton_.pos = tempPos;
140 new(&second.singleton_.restriction) std::string(std::move(tempRestriction)); 140 new(&second.singleton_.restriction) std::string(std::move(tempRestriction));
141 141
142 break; 142 break;
143 } 143 }
144 144
145 case type::group: 145 case type::group:
146 { 146 {
147 new(&second.group_.children) std::list<selrestr>(std::move(tempChildren)); 147 new(&second.group_.children) std::list<selrestr>(std::move(tempChildren));
148 second.group_.orlogic = tempOrlogic; 148 second.group_.orlogic = tempOrlogic;
149 149
150 break; 150 break;
151 } 151 }
152 152
153 case type::empty: 153 case type::empty:
154 { 154 {
155 break; 155 break;
156 } 156 }
157 } 157 }
158 } 158 }
159 159
160 selrestr::~selrestr() 160 selrestr::~selrestr()
161 { 161 {
162 switch (type_) 162 switch (type_)
@@ -165,29 +165,29 @@ namespace verbly {
165 { 165 {
166 using string_type = std::string; 166 using string_type = std::string;
167 singleton_.restriction.~string_type(); 167 singleton_.restriction.~string_type();
168 168
169 break; 169 break;
170 } 170 }
171 171
172 case type::group: 172 case type::group:
173 { 173 {
174 using list_type = std::list<selrestr>; 174 using list_type = std::list<selrestr>;
175 group_.children.~list_type(); 175 group_.children.~list_type();
176 176
177 break; 177 break;
178 } 178 }
179 179
180 case type::empty: 180 case type::empty:
181 { 181 {
182 break; 182 break;
183 } 183 }
184 } 184 }
185 } 185 }
186 186
187 selrestr::selrestr() : type_(type::empty) 187 selrestr::selrestr() : type_(type::empty)
188 { 188 {
189 } 189 }
190 190
191 selrestr::selrestr( 191 selrestr::selrestr(
192 std::string restriction, 192 std::string restriction,
193 bool pos) : 193 bool pos) :
@@ -196,7 +196,7 @@ namespace verbly {
196 new(&singleton_.restriction) std::string(std::move(restriction)); 196 new(&singleton_.restriction) std::string(std::move(restriction));
197 singleton_.pos = pos; 197 singleton_.pos = pos;
198 } 198 }
199 199
200 std::string selrestr::getRestriction() const 200 std::string selrestr::getRestriction() const
201 { 201 {
202 if (type_ == type::singleton) 202 if (type_ == type::singleton)
@@ -206,7 +206,7 @@ namespace verbly {
206 throw std::domain_error("Only singleton selrestrs have restrictions"); 206 throw std::domain_error("Only singleton selrestrs have restrictions");
207 } 207 }
208 } 208 }
209 209
210 bool selrestr::getPos() const 210 bool selrestr::getPos() const
211 { 211 {
212 if (type_ == type::singleton) 212 if (type_ == type::singleton)
@@ -216,7 +216,7 @@ namespace verbly {
216 throw std::domain_error("Only singleton selrestrs have positivity flags"); 216 throw std::domain_error("Only singleton selrestrs have positivity flags");
217 } 217 }
218 } 218 }
219 219
220 selrestr::selrestr( 220 selrestr::selrestr(
221 std::list<selrestr> children, 221 std::list<selrestr> children,
222 bool orlogic) : 222 bool orlogic) :
@@ -225,7 +225,7 @@ namespace verbly {
225 new(&group_.children) std::list<selrestr>(std::move(children)); 225 new(&group_.children) std::list<selrestr>(std::move(children));
226 group_.orlogic = orlogic; 226 group_.orlogic = orlogic;
227 } 227 }
228 228
229 std::list<selrestr> selrestr::getChildren() const 229 std::list<selrestr> selrestr::getChildren() const
230 { 230 {
231 if (type_ == type::group) 231 if (type_ == type::group)
@@ -235,7 +235,7 @@ namespace verbly {
235 throw std::domain_error("Only group selrestrs have children"); 235 throw std::domain_error("Only group selrestrs have children");
236 } 236 }
237 } 237 }
238 238
239 std::list<selrestr>::const_iterator selrestr::begin() const 239 std::list<selrestr>::const_iterator selrestr::begin() const
240 { 240 {
241 if (type_ == type::group) 241 if (type_ == type::group)
@@ -245,7 +245,7 @@ namespace verbly {
245 throw std::domain_error("Only group selrestrs have children"); 245 throw std::domain_error("Only group selrestrs have children");
246 } 246 }
247 } 247 }
248 248
249 std::list<selrestr>::const_iterator selrestr::end() const 249 std::list<selrestr>::const_iterator selrestr::end() const
250 { 250 {
251 if (type_ == type::group) 251 if (type_ == type::group)
@@ -255,7 +255,7 @@ namespace verbly {
255 throw std::domain_error("Only group selrestrs have children"); 255 throw std::domain_error("Only group selrestrs have children");
256 } 256 }
257 } 257 }
258 258
259 bool selrestr::getOrlogic() const 259 bool selrestr::getOrlogic() const
260 { 260 {
261 if (type_ == type::group) 261 if (type_ == type::group)
@@ -265,7 +265,7 @@ namespace verbly {
265 throw std::domain_error("Only group selrestrs have logic"); 265 throw std::domain_error("Only group selrestrs have logic");
266 } 266 }
267 } 267 }
268 268
269 nlohmann::json selrestr::toJson() const 269 nlohmann::json selrestr::toJson() const
270 { 270 {
271 switch (type_) 271 switch (type_)
@@ -274,7 +274,7 @@ namespace verbly {
274 { 274 {
275 return {}; 275 return {};
276 } 276 }
277 277
278 case type::singleton: 278 case type::singleton:
279 { 279 {
280 return { 280 return {
@@ -282,7 +282,7 @@ namespace verbly {
282 {"pos", singleton_.pos} 282 {"pos", singleton_.pos}
283 }; 283 };
284 } 284 }
285 285
286 case type::group: 286 case type::group:
287 { 287 {
288 std::string logic; 288 std::string logic;
@@ -292,12 +292,12 @@ namespace verbly {
292 } else { 292 } else {
293 logic = "and"; 293 logic = "and";
294 } 294 }
295 295
296 std::list<nlohmann::json> children; 296 std::list<nlohmann::json> children;
297 std::transform(std::begin(group_.children), std::end(group_.children), std::back_inserter(children), [] (const selrestr& child) { 297 std::transform(std::begin(group_.children), std::end(group_.children), std::back_inserter(children), [] (const selrestr& child) {
298 return child.toJson(); 298 return child.toJson();
299 }); 299 });
300 300
301 return { 301 return {
302 {"logic", logic}, 302 {"logic", logic},
303 {"children", children} 303 {"children", children}
diff --git a/lib/selrestr.h b/lib/selrestr.h index 9f82e3e..a7cde0a 100644 --- a/lib/selrestr.h +++ b/lib/selrestr.h
@@ -6,7 +6,7 @@
6#include "../vendor/json/json.hpp" 6#include "../vendor/json/json.hpp"
7 7
8namespace verbly { 8namespace verbly {
9 9
10 class selrestr { 10 class selrestr {
11 public: 11 public:
12 enum class type { 12 enum class type {
@@ -14,63 +14,63 @@ namespace verbly {
14 singleton, 14 singleton,
15 group 15 group
16 }; 16 };
17 17
18 // Construct from json 18 // Construct from json
19 19
20 explicit selrestr(nlohmann::json json); 20 explicit selrestr(nlohmann::json json);
21 21
22 // Copy and move constructors 22 // Copy and move constructors
23 23
24 selrestr(const selrestr& other); 24 selrestr(const selrestr& other);
25 selrestr(selrestr&& other); 25 selrestr(selrestr&& other);
26 26
27 // Assignment 27 // Assignment
28 28
29 selrestr& operator=(selrestr other); 29 selrestr& operator=(selrestr other);
30 30
31 // Swap 31 // Swap
32 32
33 friend void swap(selrestr& first, selrestr& second); 33 friend void swap(selrestr& first, selrestr& second);
34 34
35 // Destructor 35 // Destructor
36 36
37 ~selrestr(); 37 ~selrestr();
38 38
39 // Generic accessors 39 // Generic accessors
40 40
41 type getType() const 41 type getType() const
42 { 42 {
43 return type_; 43 return type_;
44 } 44 }
45 45
46 // Empty 46 // Empty
47 47
48 selrestr(); 48 selrestr();
49 49
50 // Singleton 50 // Singleton
51 51
52 selrestr(std::string restriction, bool pos); 52 selrestr(std::string restriction, bool pos);
53 53
54 std::string getRestriction() const; 54 std::string getRestriction() const;
55 55
56 bool getPos() const; 56 bool getPos() const;
57 57
58 // Group 58 // Group
59 59
60 selrestr(std::list<selrestr> children, bool orlogic); 60 selrestr(std::list<selrestr> children, bool orlogic);
61 61
62 std::list<selrestr> getChildren() const; 62 std::list<selrestr> getChildren() const;
63 63
64 std::list<selrestr>::const_iterator begin() const; 64 std::list<selrestr>::const_iterator begin() const;
65 65
66 std::list<selrestr>::const_iterator end() const; 66 std::list<selrestr>::const_iterator end() const;
67 67
68 bool getOrlogic() const; 68 bool getOrlogic() const;
69 69
70 // Helpers 70 // Helpers
71 71
72 nlohmann::json toJson() const; 72 nlohmann::json toJson() const;
73 73
74 private: 74 private:
75 union { 75 union {
76 struct { 76 struct {
diff --git a/lib/statement.cpp b/lib/statement.cpp index 222a8eb..846b9de 100644 --- a/lib/statement.cpp +++ b/lib/statement.cpp
@@ -12,22 +12,22 @@
12#include "pronunciation.h" 12#include "pronunciation.h"
13 13
14namespace verbly { 14namespace verbly {
15 15
16 statement::statement( 16 statement::statement(
17 object context, 17 object context,
18 filter queryFilter) : 18 filter queryFilter) :
19 statement(getTableForContext(context), queryFilter.compact().normalize(context)) 19 statement(getTableForContext(context), queryFilter.compact().normalize(context))
20 { 20 {
21 } 21 }
22 22
23 std::string statement::getQueryString(std::list<std::string> select, bool random, int limit) const 23 std::string statement::getQueryString(std::list<std::string> select, bool random, int limit) const
24 { 24 {
25 std::stringstream queryStream; 25 std::stringstream queryStream;
26 26
27 if (!withs_.empty()) 27 if (!withs_.empty())
28 { 28 {
29 queryStream << "WITH RECURSIVE "; 29 queryStream << "WITH RECURSIVE ";
30 30
31 std::list<std::string> ctes; 31 std::list<std::string> ctes;
32 for (const with& cte : withs_) 32 for (const with& cte : withs_)
33 { 33 {
@@ -39,19 +39,19 @@ namespace verbly {
39 cteStream << cte.getTableForId(cte.getTopTable()); 39 cteStream << cte.getTableForId(cte.getTopTable());
40 cteStream << " AS "; 40 cteStream << " AS ";
41 cteStream << cte.getTopTable(); 41 cteStream << cte.getTopTable();
42 42
43 for (const join& j : cte.getJoins()) 43 for (const join& j : cte.getJoins())
44 { 44 {
45 cteStream << " "; 45 cteStream << " ";
46 cteStream << j; 46 cteStream << j;
47 } 47 }
48 48
49 if (cte.getCondition().getType() != condition::type::empty) 49 if (cte.getCondition().getType() != condition::type::empty)
50 { 50 {
51 cteStream << " WHERE "; 51 cteStream << " WHERE ";
52 cteStream << cte.getCondition().toSql(); 52 cteStream << cte.getCondition().toSql();
53 } 53 }
54 54
55 if (cte.isRecursive()) 55 if (cte.isRecursive())
56 { 56 {
57 cteStream << " UNION SELECT l.* FROM "; 57 cteStream << " UNION SELECT l.* FROM ";
@@ -69,59 +69,59 @@ namespace verbly {
69 cteStream << " = l."; 69 cteStream << " = l.";
70 cteStream << cte.getField().getColumn(); 70 cteStream << cte.getField().getColumn();
71 } 71 }
72 72
73 cteStream << ")"; 73 cteStream << ")";
74 74
75 ctes.push_back(cteStream.str()); 75 ctes.push_back(cteStream.str());
76 } 76 }
77 77
78 queryStream << implode(std::begin(ctes), std::end(ctes), ", "); 78 queryStream << implode(std::begin(ctes), std::end(ctes), ", ");
79 queryStream << " "; 79 queryStream << " ";
80 } 80 }
81 81
82 std::list<std::string> realSelect; 82 std::list<std::string> realSelect;
83 for (std::string& s : select) 83 for (std::string& s : select)
84 { 84 {
85 realSelect.push_back(topTable_ + "." + s); 85 realSelect.push_back(topTable_ + "." + s);
86 } 86 }
87 87
88 queryStream << "SELECT "; 88 queryStream << "SELECT ";
89 queryStream << implode(std::begin(realSelect), std::end(realSelect), ", "); 89 queryStream << implode(std::begin(realSelect), std::end(realSelect), ", ");
90 queryStream << " FROM "; 90 queryStream << " FROM ";
91 queryStream << tables_.at(topTable_); 91 queryStream << tables_.at(topTable_);
92 queryStream << " AS "; 92 queryStream << " AS ";
93 queryStream << topTable_; 93 queryStream << topTable_;
94 94
95 for (const join& j : joins_) 95 for (const join& j : joins_)
96 { 96 {
97 queryStream << " "; 97 queryStream << " ";
98 queryStream << j; 98 queryStream << j;
99 } 99 }
100 100
101 if (topCondition_.getType() != condition::type::empty) 101 if (topCondition_.getType() != condition::type::empty)
102 { 102 {
103 queryStream << " WHERE "; 103 queryStream << " WHERE ";
104 queryStream << topCondition_.toSql(); 104 queryStream << topCondition_.toSql();
105 } 105 }
106 106
107 if (random) 107 if (random)
108 { 108 {
109 queryStream << " ORDER BY RANDOM()"; 109 queryStream << " ORDER BY RANDOM()";
110 } 110 }
111 111
112 if (limit > 0) 112 if (limit > 0)
113 { 113 {
114 queryStream << " LIMIT "; 114 queryStream << " LIMIT ";
115 queryStream << limit; 115 queryStream << limit;
116 } 116 }
117 117
118 return queryStream.str(); 118 return queryStream.str();
119 } 119 }
120 120
121 std::list<binding> statement::getBindings() const 121 std::list<binding> statement::getBindings() const
122 { 122 {
123 std::list<binding> result; 123 std::list<binding> result;
124 124
125 for (const with& w : withs_) 125 for (const with& w : withs_)
126 { 126 {
127 for (binding value : w.getCondition().flattenBindings()) 127 for (binding value : w.getCondition().flattenBindings())
@@ -129,15 +129,15 @@ namespace verbly {
129 result.push_back(std::move(value)); 129 result.push_back(std::move(value));
130 } 130 }
131 } 131 }
132 132
133 for (binding value : topCondition_.flattenBindings()) 133 for (binding value : topCondition_.flattenBindings())
134 { 134 {
135 result.push_back(std::move(value)); 135 result.push_back(std::move(value));
136 } 136 }
137 137
138 return result; 138 return result;
139 } 139 }
140 140
141 statement::statement( 141 statement::statement(
142 std::string tableName, 142 std::string tableName,
143 filter clause, 143 filter clause,
@@ -149,7 +149,7 @@ namespace verbly {
149 topCondition_(parseFilter(std::move(clause))) 149 topCondition_(parseFilter(std::move(clause)))
150 { 150 {
151 } 151 }
152 152
153 /** 153 /**
154 * This function recursively parses the query's filter condition. It is not 154 * This function recursively parses the query's filter condition. It is not
155 * idempotent. It returns a condition object representing the passed filter, 155 * idempotent. It returns a condition object representing the passed filter,
@@ -165,7 +165,7 @@ namespace verbly {
165 { 165 {
166 return {}; 166 return {};
167 } 167 }
168 168
169 case filter::type::singleton: 169 case filter::type::singleton:
170 { 170 {
171 switch (clause.getField().getType()) 171 switch (clause.getField().getType())
@@ -174,7 +174,7 @@ namespace verbly {
174 { 174 {
175 return {}; 175 return {};
176 } 176 }
177 177
178 // For primitive type filters, all we need to do is translate the 178 // For primitive type filters, all we need to do is translate the
179 // filter object directly into a condition object. No joins are 179 // filter object directly into a condition object. No joins are
180 // necessary. 180 // necessary.
@@ -188,67 +188,67 @@ namespace verbly {
188 { 188 {
189 return condition(topTable_, clause.getField().getColumn(), true); 189 return condition(topTable_, clause.getField().getColumn(), true);
190 } 190 }
191 191
192 case filter::comparison::is_not_null: 192 case filter::comparison::is_not_null:
193 { 193 {
194 return condition(topTable_, clause.getField().getColumn(), false); 194 return condition(topTable_, clause.getField().getColumn(), false);
195 } 195 }
196 196
197 case filter::comparison::int_equals: 197 case filter::comparison::int_equals:
198 { 198 {
199 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getIntegerArgument()); 199 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getIntegerArgument());
200 } 200 }
201 201
202 case filter::comparison::int_does_not_equal: 202 case filter::comparison::int_does_not_equal:
203 { 203 {
204 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getIntegerArgument()); 204 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getIntegerArgument());
205 } 205 }
206 206
207 case filter::comparison::int_is_at_least: 207 case filter::comparison::int_is_at_least:
208 { 208 {
209 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_least, clause.getIntegerArgument()); 209 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_least, clause.getIntegerArgument());
210 } 210 }
211 211
212 case filter::comparison::int_is_greater_than: 212 case filter::comparison::int_is_greater_than:
213 { 213 {
214 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_greater_than, clause.getIntegerArgument()); 214 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_greater_than, clause.getIntegerArgument());
215 } 215 }
216 216
217 case filter::comparison::int_is_at_most: 217 case filter::comparison::int_is_at_most:
218 { 218 {
219 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_most, clause.getIntegerArgument()); 219 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_most, clause.getIntegerArgument());
220 } 220 }
221 221
222 case filter::comparison::int_is_less_than: 222 case filter::comparison::int_is_less_than:
223 { 223 {
224 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_less_than, clause.getIntegerArgument()); 224 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_less_than, clause.getIntegerArgument());
225 } 225 }
226 226
227 case filter::comparison::boolean_equals: 227 case filter::comparison::boolean_equals:
228 { 228 {
229 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getBooleanArgument() ? 1 : 0); 229 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getBooleanArgument() ? 1 : 0);
230 } 230 }
231 231
232 case filter::comparison::string_equals: 232 case filter::comparison::string_equals:
233 { 233 {
234 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getStringArgument()); 234 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getStringArgument());
235 } 235 }
236 236
237 case filter::comparison::string_does_not_equal: 237 case filter::comparison::string_does_not_equal:
238 { 238 {
239 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getStringArgument()); 239 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getStringArgument());
240 } 240 }
241 241
242 case filter::comparison::string_is_like: 242 case filter::comparison::string_is_like:
243 { 243 {
244 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_like, clause.getStringArgument()); 244 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_like, clause.getStringArgument());
245 } 245 }
246 246
247 case filter::comparison::string_is_not_like: 247 case filter::comparison::string_is_not_like:
248 { 248 {
249 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_not_like, clause.getStringArgument()); 249 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_not_like, clause.getStringArgument());
250 } 250 }
251 251
252 case filter::comparison::matches: 252 case filter::comparison::matches:
253 case filter::comparison::does_not_match: 253 case filter::comparison::does_not_match:
254 case filter::comparison::hierarchally_matches: 254 case filter::comparison::hierarchally_matches:
@@ -258,7 +258,7 @@ namespace verbly {
258 } 258 }
259 } 259 }
260 } 260 }
261 261
262 case field::type::join: 262 case field::type::join:
263 { 263 {
264 // First, figure out what table we need to join against. 264 // First, figure out what table we need to join against.
@@ -278,9 +278,9 @@ namespace verbly {
278 clause.getJoinCondition().normalize(clause.getField().getJoinObject()), 278 clause.getJoinCondition().normalize(clause.getField().getJoinObject()),
279 nextTableId_, 279 nextTableId_,
280 nextWithId_); 280 nextWithId_);
281 281
282 std::string joinTable = joinStmt.topTable_; 282 std::string joinTable = joinStmt.topTable_;
283 283
284 if (clause.getComparison() == filter::comparison::does_not_match) 284 if (clause.getComparison() == filter::comparison::does_not_match)
285 { 285 {
286 // If the comparison is actually a negative filter, we can't just 286 // If the comparison is actually a negative filter, we can't just
@@ -293,7 +293,7 @@ namespace verbly {
293 // condition on the join column being NULL as before. 293 // condition on the join column being NULL as before.
294 std::string withName = instantiateWith(clause.getField().getTable()); 294 std::string withName = instantiateWith(clause.getField().getTable());
295 std::string withInstName = instantiateTable(withName); 295 std::string withInstName = instantiateTable(withName);
296 296
297 // LEFT JOIN against the CTE. 297 // LEFT JOIN against the CTE.
298 joins_.emplace_back( 298 joins_.emplace_back(
299 true, 299 true,
@@ -310,7 +310,7 @@ namespace verbly {
310 std::map<std::string, std::string> cteTables = std::move(joinStmt.tables_); 310 std::map<std::string, std::string> cteTables = std::move(joinStmt.tables_);
311 std::list<join> cteJoins = std::move(joinStmt.joins_); 311 std::list<join> cteJoins = std::move(joinStmt.joins_);
312 condition cteCondition = integrate(std::move(joinStmt), true); 312 condition cteCondition = integrate(std::move(joinStmt), true);
313 313
314 withs_.emplace_back( 314 withs_.emplace_back(
315 std::move(withName), 315 std::move(withName),
316 clause.getField(), 316 clause.getField(),
@@ -319,7 +319,7 @@ namespace verbly {
319 std::move(cteCondition), 319 std::move(cteCondition),
320 std::move(cteJoins), 320 std::move(cteJoins),
321 false); 321 false);
322 322
323 // Condition on the join column being NULL, which causes the query 323 // Condition on the join column being NULL, which causes the query
324 // to only return results that do not match the subquery. 324 // to only return results that do not match the subquery.
325 return condition(std::move(withInstName), clause.getField().getColumn(), true); 325 return condition(std::move(withInstName), clause.getField().getColumn(), true);
@@ -332,14 +332,14 @@ namespace verbly {
332 clause.getField().getColumn(), 332 clause.getField().getColumn(),
333 std::move(joinTable), 333 std::move(joinTable),
334 clause.getField().getColumn()); 334 clause.getField().getColumn());
335 335
336 // Integrate the subquery's table mappings, joins, and CTEs into 336 // Integrate the subquery's table mappings, joins, and CTEs into
337 // this statement, and return the subquery condition as our 337 // this statement, and return the subquery condition as our
338 // condition. 338 // condition.
339 return integrate(std::move(joinStmt)); 339 return integrate(std::move(joinStmt));
340 } 340 }
341 } 341 }
342 342
343 case field::type::join_through: 343 case field::type::join_through:
344 { 344 {
345 // Recursively parse the subquery, and therefore obtain an 345 // Recursively parse the subquery, and therefore obtain an
@@ -350,9 +350,9 @@ namespace verbly {
350 clause.getJoinCondition().normalize(clause.getField().getJoinObject()), 350 clause.getJoinCondition().normalize(clause.getField().getJoinObject()),
351 nextTableId_, 351 nextTableId_,
352 nextWithId_); 352 nextWithId_);
353 353
354 std::string joinTable = joinStmt.topTable_; 354 std::string joinTable = joinStmt.topTable_;
355 355
356 if (clause.getComparison() == filter::comparison::does_not_match) 356 if (clause.getComparison() == filter::comparison::does_not_match)
357 { 357 {
358 // If the comparison is actually a negative filter, we can't just 358 // If the comparison is actually a negative filter, we can't just
@@ -366,7 +366,7 @@ namespace verbly {
366 // condition on the join column being NULL as before. 366 // condition on the join column being NULL as before.
367 std::string withName = instantiateWith(clause.getField().getTable()); 367 std::string withName = instantiateWith(clause.getField().getTable());
368 std::string withInstName = instantiateTable(withName); 368 std::string withInstName = instantiateTable(withName);
369 369
370 // LEFT JOIN against the CTE. 370 // LEFT JOIN against the CTE.
371 joins_.emplace_back( 371 joins_.emplace_back(
372 true, 372 true,
@@ -375,7 +375,7 @@ namespace verbly {
375 clause.getField().getColumn(), 375 clause.getField().getColumn(),
376 withInstName, 376 withInstName,
377 clause.getField().getJoinColumn()); 377 clause.getField().getJoinColumn());
378 378
379 // Modify the substatement such that the through table is the top 379 // Modify the substatement such that the through table is the top
380 // table, and such that it joins against the previous top table. 380 // table, and such that it joins against the previous top table.
381 std::string throughTable = joinStmt.instantiateTable(clause.getField().getTable()); 381 std::string throughTable = joinStmt.instantiateTable(clause.getField().getTable());
@@ -386,7 +386,7 @@ namespace verbly {
386 clause.getField().getForeignJoinColumn(), 386 clause.getField().getForeignJoinColumn(),
387 std::move(joinTable), 387 std::move(joinTable),
388 clause.getField().getForeignColumn()); 388 clause.getField().getForeignColumn());
389 389
390 joinStmt.topTable_ = throughTable; 390 joinStmt.topTable_ = throughTable;
391 391
392 // All CTEs have to be in the main statement, so integrate any 392 // All CTEs have to be in the main statement, so integrate any
@@ -396,7 +396,7 @@ namespace verbly {
396 std::map<std::string, std::string> cteTables = std::move(joinStmt.tables_); 396 std::map<std::string, std::string> cteTables = std::move(joinStmt.tables_);
397 std::list<join> cteJoins = std::move(joinStmt.joins_); 397 std::list<join> cteJoins = std::move(joinStmt.joins_);
398 condition cteCondition = integrate(std::move(joinStmt), true); 398 condition cteCondition = integrate(std::move(joinStmt), true);
399 399
400 withs_.emplace_back( 400 withs_.emplace_back(
401 std::move(withName), 401 std::move(withName),
402 clause.getField(), 402 clause.getField(),
@@ -405,14 +405,14 @@ namespace verbly {
405 std::move(cteCondition), 405 std::move(cteCondition),
406 std::move(cteJoins), 406 std::move(cteJoins),
407 false); 407 false);
408 408
409 // Condition on the join column being NULL, which causes the query 409 // Condition on the join column being NULL, which causes the query
410 // to only return results that do not match the subquery. 410 // to only return results that do not match the subquery.
411 return condition(std::move(withInstName), clause.getField().getJoinColumn(), true); 411 return condition(std::move(withInstName), clause.getField().getJoinColumn(), true);
412 } else { 412 } else {
413 // Instantiate the through table. 413 // Instantiate the through table.
414 std::string throughTable = instantiateTable(clause.getField().getTable()); 414 std::string throughTable = instantiateTable(clause.getField().getTable());
415 415
416 // INNER JOIN against the through table. 416 // INNER JOIN against the through table.
417 joins_.emplace_back( 417 joins_.emplace_back(
418 false, 418 false,
@@ -421,7 +421,7 @@ namespace verbly {
421 clause.getField().getColumn(), 421 clause.getField().getColumn(),
422 throughTable, 422 throughTable,
423 clause.getField().getJoinColumn()); 423 clause.getField().getJoinColumn());
424 424
425 // INNER JOIN from the through table to the top table of the subquery. 425 // INNER JOIN from the through table to the top table of the subquery.
426 joins_.emplace_back( 426 joins_.emplace_back(
427 false, 427 false,
@@ -430,20 +430,20 @@ namespace verbly {
430 clause.getField().getForeignJoinColumn(), 430 clause.getField().getForeignJoinColumn(),
431 std::move(joinTable), 431 std::move(joinTable),
432 clause.getField().getForeignColumn()); 432 clause.getField().getForeignColumn());
433 433
434 // Integrate the subquery's table mappings, joins, and CTEs into 434 // Integrate the subquery's table mappings, joins, and CTEs into
435 // this statement, and return the subquery condition as our 435 // this statement, and return the subquery condition as our
436 // condition. 436 // condition.
437 return integrate(std::move(joinStmt)); 437 return integrate(std::move(joinStmt));
438 } 438 }
439 } 439 }
440 440
441 case field::type::hierarchal_join: 441 case field::type::hierarchal_join:
442 { 442 {
443 // Create a recursive CTE that represents the results of the subquery. 443 // Create a recursive CTE that represents the results of the subquery.
444 std::string withName = instantiateWith(clause.getField().getTable()); 444 std::string withName = instantiateWith(clause.getField().getTable());
445 std::string withInstName = instantiateTable(withName); 445 std::string withInstName = instantiateTable(withName);
446 446
447 // If we are matching against the subquery, we INNER JOIN with the 447 // If we are matching against the subquery, we INNER JOIN with the
448 // CTE. If we are negatively matching the subquery, we LEFT JOIN 448 // CTE. If we are negatively matching the subquery, we LEFT JOIN
449 // with the CTE. 449 // with the CTE.
@@ -452,7 +452,7 @@ namespace verbly {
452 { 452 {
453 outer = true; 453 outer = true;
454 } 454 }
455 455
456 // Join against the CTE. 456 // Join against the CTE.
457 joins_.emplace_back( 457 joins_.emplace_back(
458 outer, 458 outer,
@@ -461,14 +461,14 @@ namespace verbly {
461 clause.getField().getColumn(), 461 clause.getField().getColumn(),
462 withInstName, 462 withInstName,
463 clause.getField().getColumn()); 463 clause.getField().getColumn());
464 464
465 // Recursively parse the subquery in order to create the CTE. 465 // Recursively parse the subquery in order to create the CTE.
466 statement withStmt( 466 statement withStmt(
467 getTableForContext(clause.getField().getObject()), 467 getTableForContext(clause.getField().getObject()),
468 clause.getJoinCondition().normalize(clause.getField().getObject()), 468 clause.getJoinCondition().normalize(clause.getField().getObject()),
469 nextTableId_, 469 nextTableId_,
470 nextWithId_); 470 nextWithId_);
471 471
472 // All CTEs have to be in the main statement, so integrate any CTEs 472 // All CTEs have to be in the main statement, so integrate any CTEs
473 // that our subquery uses. Also, retrieve the table mapping, joins 473 // that our subquery uses. Also, retrieve the table mapping, joins
474 // list, and subquery condition, and use them to create the CTE. 474 // list, and subquery condition, and use them to create the CTE.
@@ -476,7 +476,7 @@ namespace verbly {
476 std::map<std::string, std::string> cteTables = std::move(withStmt.tables_); 476 std::map<std::string, std::string> cteTables = std::move(withStmt.tables_);
477 std::list<join> cteJoins = std::move(withStmt.joins_); 477 std::list<join> cteJoins = std::move(withStmt.joins_);
478 condition cteCondition = integrate(std::move(withStmt), true); 478 condition cteCondition = integrate(std::move(withStmt), true);
479 479
480 withs_.emplace_back( 480 withs_.emplace_back(
481 std::move(withName), 481 std::move(withName),
482 clause.getField(), 482 clause.getField(),
@@ -498,11 +498,11 @@ namespace verbly {
498 } 498 }
499 } 499 }
500 } 500 }
501 501
502 case filter::type::group: 502 case filter::type::group:
503 { 503 {
504 condition grp(clause.getOrlogic()); 504 condition grp(clause.getOrlogic());
505 505
506 for (const filter& child : clause) 506 for (const filter& child : clause)
507 { 507 {
508 condition newChild = parseFilter(child); 508 condition newChild = parseFilter(child);
@@ -511,30 +511,30 @@ namespace verbly {
511 grp += std::move(newChild); 511 grp += std::move(newChild);
512 } 512 }
513 } 513 }
514 514
515 if (grp.getChildren().empty()) 515 if (grp.getChildren().empty())
516 { 516 {
517 grp = {}; 517 grp = {};
518 } 518 }
519 519
520 return grp; 520 return grp;
521 } 521 }
522 } 522 }
523 } 523 }
524 524
525 std::string statement::instantiateTable(std::string name) 525 std::string statement::instantiateTable(std::string name)
526 { 526 {
527 std::string identifier = name + "_" + std::to_string(nextTableId_++); 527 std::string identifier = name + "_" + std::to_string(nextTableId_++);
528 tables_[identifier] = name; 528 tables_[identifier] = name;
529 529
530 return identifier; 530 return identifier;
531 } 531 }
532 532
533 std::string statement::instantiateWith(std::string name) 533 std::string statement::instantiateWith(std::string name)
534 { 534 {
535 return name + "_tree_" + std::to_string(nextWithId_++); 535 return name + "_tree_" + std::to_string(nextWithId_++);
536 } 536 }
537 537
538 /** 538 /**
539 * This method integrates the parts of a recursively generated statement into 539 * This method integrates the parts of a recursively generated statement into
540 * this statement. This is used because filters are recursive objects, but 540 * this statement. This is used because filters are recursive objects, but
@@ -551,13 +551,13 @@ namespace verbly {
551 { 551 {
552 tables_[mapping.first] = mapping.second; 552 tables_[mapping.first] = mapping.second;
553 } 553 }
554 554
555 for (auto& j : subStmt.joins_) 555 for (auto& j : subStmt.joins_)
556 { 556 {
557 joins_.push_back(j); 557 joins_.push_back(j);
558 } 558 }
559 } 559 }
560 560
561 for (auto& w : subStmt.withs_) 561 for (auto& w : subStmt.withs_)
562 { 562 {
563 withs_.push_back(w); 563 withs_.push_back(w);
@@ -565,10 +565,10 @@ namespace verbly {
565 565
566 nextTableId_ = subStmt.nextTableId_; 566 nextTableId_ = subStmt.nextTableId_;
567 nextWithId_ = subStmt.nextWithId_; 567 nextWithId_ = subStmt.nextWithId_;
568 568
569 return subStmt.topCondition_; 569 return subStmt.topCondition_;
570 } 570 }
571 571
572 std::ostream& operator<<(std::ostream& oss, const statement::join& j) 572 std::ostream& operator<<(std::ostream& oss, const statement::join& j)
573 { 573 {
574 if (j.isOuterJoin()) 574 if (j.isOuterJoin())
@@ -577,7 +577,7 @@ namespace verbly {
577 } else { 577 } else {
578 oss << "INNER"; 578 oss << "INNER";
579 } 579 }
580 580
581 return oss 581 return oss
582 << " JOIN " 582 << " JOIN "
583 << j.getForeignTableName() 583 << j.getForeignTableName()
@@ -592,55 +592,55 @@ namespace verbly {
592 << "." 592 << "."
593 << j.getJoinColumn(); 593 << j.getJoinColumn();
594 } 594 }
595 595
596 statement::condition::condition(const condition& other) 596 statement::condition::condition(const condition& other)
597 { 597 {
598 type_ = other.type_; 598 type_ = other.type_;
599 599
600 switch (type_) 600 switch (type_)
601 { 601 {
602 case type::empty: 602 case type::empty:
603 { 603 {
604 break; 604 break;
605 } 605 }
606 606
607 case type::singleton: 607 case type::singleton:
608 { 608 {
609 new(&singleton_.table_) std::string(other.singleton_.table_); 609 new(&singleton_.table_) std::string(other.singleton_.table_);
610 new(&singleton_.column_) std::string(other.singleton_.column_); 610 new(&singleton_.column_) std::string(other.singleton_.column_);
611 singleton_.comparison_ = other.singleton_.comparison_; 611 singleton_.comparison_ = other.singleton_.comparison_;
612 new(&singleton_.value_) binding(other.singleton_.value_); 612 new(&singleton_.value_) binding(other.singleton_.value_);
613 613
614 break; 614 break;
615 } 615 }
616 616
617 case type::group: 617 case type::group:
618 { 618 {
619 new(&group_.children_) std::list<condition>(other.group_.children_); 619 new(&group_.children_) std::list<condition>(other.group_.children_);
620 group_.orlogic_ = other.group_.orlogic_; 620 group_.orlogic_ = other.group_.orlogic_;
621 621
622 break; 622 break;
623 } 623 }
624 } 624 }
625 } 625 }
626 626
627 statement::condition::condition(condition&& other) : condition() 627 statement::condition::condition(condition&& other) : condition()
628 { 628 {
629 swap(*this, other); 629 swap(*this, other);
630 } 630 }
631 631
632 statement::condition& statement::condition::operator=(condition other) 632 statement::condition& statement::condition::operator=(condition other)
633 { 633 {
634 swap(*this, other); 634 swap(*this, other);
635 635
636 return *this; 636 return *this;
637 } 637 }
638 638
639 void swap(statement::condition& first, statement::condition& second) 639 void swap(statement::condition& first, statement::condition& second)
640 { 640 {
641 using type = statement::condition::type; 641 using type = statement::condition::type;
642 using condition = statement::condition; 642 using condition = statement::condition;
643 643
644 type tempType = first.type_; 644 type tempType = first.type_;
645 std::string tempTable; 645 std::string tempTable;
646 std::string tempColumn; 646 std::string tempColumn;
@@ -648,94 +648,94 @@ namespace verbly {
648 binding tempBinding; 648 binding tempBinding;
649 std::list<condition> tempChildren; 649 std::list<condition> tempChildren;
650 bool tempOrlogic; 650 bool tempOrlogic;
651 651
652 switch (tempType) 652 switch (tempType)
653 { 653 {
654 case type::empty: 654 case type::empty:
655 { 655 {
656 break; 656 break;
657 } 657 }
658 658
659 case type::singleton: 659 case type::singleton:
660 { 660 {
661 tempTable = std::move(first.singleton_.table_); 661 tempTable = std::move(first.singleton_.table_);
662 tempColumn = std::move(first.singleton_.column_); 662 tempColumn = std::move(first.singleton_.column_);
663 tempComparison = first.singleton_.comparison_; 663 tempComparison = first.singleton_.comparison_;
664 tempBinding = std::move(first.singleton_.value_); 664 tempBinding = std::move(first.singleton_.value_);
665 665
666 break; 666 break;
667 } 667 }
668 668
669 case type::group: 669 case type::group:
670 { 670 {
671 tempChildren = std::move(first.group_.children_); 671 tempChildren = std::move(first.group_.children_);
672 tempOrlogic = first.group_.orlogic_; 672 tempOrlogic = first.group_.orlogic_;
673 673
674 break; 674 break;
675 } 675 }
676 } 676 }
677 677
678 first.~condition(); 678 first.~condition();
679 679
680 first.type_ = second.type_; 680 first.type_ = second.type_;
681 681
682 switch (first.type_) 682 switch (first.type_)
683 { 683 {
684 case type::empty: 684 case type::empty:
685 { 685 {
686 break; 686 break;
687 } 687 }
688 688
689 case type::singleton: 689 case type::singleton:
690 { 690 {
691 new(&first.singleton_.table_) std::string(std::move(second.singleton_.table_)); 691 new(&first.singleton_.table_) std::string(std::move(second.singleton_.table_));
692 new(&first.singleton_.column_) std::string(std::move(second.singleton_.column_)); 692 new(&first.singleton_.column_) std::string(std::move(second.singleton_.column_));
693 first.singleton_.comparison_ = second.singleton_.comparison_; 693 first.singleton_.comparison_ = second.singleton_.comparison_;
694 new(&first.singleton_.value_) binding(std::move(second.singleton_.value_)); 694 new(&first.singleton_.value_) binding(std::move(second.singleton_.value_));
695 695
696 break; 696 break;
697 } 697 }
698 698
699 case type::group: 699 case type::group:
700 { 700 {
701 new(&first.group_.children_) std::list<condition>(std::move(second.group_.children_)); 701 new(&first.group_.children_) std::list<condition>(std::move(second.group_.children_));
702 first.group_.orlogic_ = second.group_.orlogic_; 702 first.group_.orlogic_ = second.group_.orlogic_;
703 703
704 break; 704 break;
705 } 705 }
706 } 706 }
707 707
708 second.~condition(); 708 second.~condition();
709 709
710 second.type_ = tempType; 710 second.type_ = tempType;
711 711
712 switch (second.type_) 712 switch (second.type_)
713 { 713 {
714 case type::empty: 714 case type::empty:
715 { 715 {
716 break; 716 break;
717 } 717 }
718 718
719 case type::singleton: 719 case type::singleton:
720 { 720 {
721 new(&second.singleton_.table_) std::string(std::move(tempTable)); 721 new(&second.singleton_.table_) std::string(std::move(tempTable));
722 new(&second.singleton_.column_) std::string(std::move(tempColumn)); 722 new(&second.singleton_.column_) std::string(std::move(tempColumn));
723 second.singleton_.comparison_ = tempComparison; 723 second.singleton_.comparison_ = tempComparison;
724 new(&second.singleton_.value_) binding(std::move(tempBinding)); 724 new(&second.singleton_.value_) binding(std::move(tempBinding));
725 725
726 break; 726 break;
727 } 727 }
728 728
729 case type::group: 729 case type::group:
730 { 730 {
731 new(&second.group_.children_) std::list<condition>(std::move(tempChildren)); 731 new(&second.group_.children_) std::list<condition>(std::move(tempChildren));
732 second.group_.orlogic_ = tempOrlogic; 732 second.group_.orlogic_ = tempOrlogic;
733 733
734 break; 734 break;
735 } 735 }
736 } 736 }
737 } 737 }
738 738
739 statement::condition::~condition() 739 statement::condition::~condition()
740 { 740 {
741 switch (type_) 741 switch (type_)
@@ -744,33 +744,33 @@ namespace verbly {
744 { 744 {
745 break; 745 break;
746 } 746 }
747 747
748 case type::singleton: 748 case type::singleton:
749 { 749 {
750 using string_type = std::string; 750 using string_type = std::string;
751 751
752 singleton_.table_.~string_type(); 752 singleton_.table_.~string_type();
753 singleton_.column_.~string_type(); 753 singleton_.column_.~string_type();
754 singleton_.value_.~binding(); 754 singleton_.value_.~binding();
755 755
756 break; 756 break;
757 } 757 }
758 758
759 case type::group: 759 case type::group:
760 { 760 {
761 using list_type = std::list<condition>; 761 using list_type = std::list<condition>;
762 762
763 group_.children_.~list_type(); 763 group_.children_.~list_type();
764 764
765 break; 765 break;
766 } 766 }
767 } 767 }
768 } 768 }
769 769
770 statement::condition::condition() : type_(type::empty) 770 statement::condition::condition() : type_(type::empty)
771 { 771 {
772 } 772 }
773 773
774 statement::condition::condition( 774 statement::condition::condition(
775 std::string table, 775 std::string table,
776 std::string column, 776 std::string column,
@@ -779,7 +779,7 @@ namespace verbly {
779 { 779 {
780 new(&singleton_.table_) std::string(std::move(table)); 780 new(&singleton_.table_) std::string(std::move(table));
781 new(&singleton_.column_) std::string(std::move(column)); 781 new(&singleton_.column_) std::string(std::move(column));
782 782
783 if (isNull) 783 if (isNull)
784 { 784 {
785 singleton_.comparison_ = comparison::is_null; 785 singleton_.comparison_ = comparison::is_null;
@@ -787,7 +787,7 @@ namespace verbly {
787 singleton_.comparison_ = comparison::is_not_null; 787 singleton_.comparison_ = comparison::is_not_null;
788 } 788 }
789 } 789 }
790 790
791 statement::condition::condition( 791 statement::condition::condition(
792 std::string table, 792 std::string table,
793 std::string column, 793 std::string column,
@@ -800,7 +800,7 @@ namespace verbly {
800 singleton_.comparison_ = comp; 800 singleton_.comparison_ = comp;
801 new(&singleton_.value_) binding(std::move(value)); 801 new(&singleton_.value_) binding(std::move(value));
802 } 802 }
803 803
804 std::string statement::condition::toSql() const 804 std::string statement::condition::toSql() const
805 { 805 {
806 switch (type_) 806 switch (type_)
@@ -809,7 +809,7 @@ namespace verbly {
809 { 809 {
810 return ""; 810 return "";
811 } 811 }
812 812
813 case type::singleton: 813 case type::singleton:
814 { 814 {
815 switch (singleton_.comparison_) 815 switch (singleton_.comparison_)
@@ -818,54 +818,54 @@ namespace verbly {
818 { 818 {
819 return singleton_.table_ + "." + singleton_.column_ + " = ?"; 819 return singleton_.table_ + "." + singleton_.column_ + " = ?";
820 } 820 }
821 821
822 case comparison::does_not_equal: 822 case comparison::does_not_equal:
823 { 823 {
824 return singleton_.table_ + "." + singleton_.column_ + " != ?"; 824 return singleton_.table_ + "." + singleton_.column_ + " != ?";
825 } 825 }
826 826
827 case comparison::is_greater_than: 827 case comparison::is_greater_than:
828 { 828 {
829 return singleton_.table_ + "." + singleton_.column_ + " > ?"; 829 return singleton_.table_ + "." + singleton_.column_ + " > ?";
830 } 830 }
831 831
832 case comparison::is_at_most: 832 case comparison::is_at_most:
833 { 833 {
834 return singleton_.table_ + "." + singleton_.column_ + " <= ?"; 834 return singleton_.table_ + "." + singleton_.column_ + " <= ?";
835 } 835 }
836 836
837 case comparison::is_less_than: 837 case comparison::is_less_than:
838 { 838 {
839 return singleton_.table_ + "." + singleton_.column_ + " < ?"; 839 return singleton_.table_ + "." + singleton_.column_ + " < ?";
840 } 840 }
841 841
842 case comparison::is_at_least: 842 case comparison::is_at_least:
843 { 843 {
844 return singleton_.table_ + "." + singleton_.column_ + " >= ?"; 844 return singleton_.table_ + "." + singleton_.column_ + " >= ?";
845 } 845 }
846 846
847 case comparison::is_like: 847 case comparison::is_like:
848 { 848 {
849 return singleton_.table_ + "." + singleton_.column_ + " LIKE ?"; 849 return singleton_.table_ + "." + singleton_.column_ + " LIKE ?";
850 } 850 }
851 851
852 case comparison::is_not_like: 852 case comparison::is_not_like:
853 { 853 {
854 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE ?"; 854 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE ?";
855 } 855 }
856 856
857 case comparison::is_not_null: 857 case comparison::is_not_null:
858 { 858 {
859 return singleton_.table_ + "." + singleton_.column_ + " IS NOT NULL"; 859 return singleton_.table_ + "." + singleton_.column_ + " IS NOT NULL";
860 } 860 }
861 861
862 case comparison::is_null: 862 case comparison::is_null:
863 { 863 {
864 return singleton_.table_ + "." + singleton_.column_ + " IS NULL"; 864 return singleton_.table_ + "." + singleton_.column_ + " IS NULL";
865 } 865 }
866 } 866 }
867 } 867 }
868 868
869 case type::group: 869 case type::group:
870 { 870 {
871 std::list<std::string> clauses; 871 std::list<std::string> clauses;
@@ -873,12 +873,12 @@ namespace verbly {
873 { 873 {
874 clauses.push_back(cond.toSql()); 874 clauses.push_back(cond.toSql());
875 } 875 }
876 876
877 return implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND "); 877 return implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND ");
878 } 878 }
879 } 879 }
880 } 880 }
881 881
882 std::list<binding> statement::condition::flattenBindings() const 882 std::list<binding> statement::condition::flattenBindings() const
883 { 883 {
884 switch (type_) 884 switch (type_)
@@ -887,7 +887,7 @@ namespace verbly {
887 { 887 {
888 return {}; 888 return {};
889 } 889 }
890 890
891 case type::singleton: 891 case type::singleton:
892 { 892 {
893 switch (singleton_.comparison_) 893 switch (singleton_.comparison_)
@@ -903,7 +903,7 @@ namespace verbly {
903 { 903 {
904 return {singleton_.value_}; 904 return {singleton_.value_};
905 } 905 }
906 906
907 case comparison::is_not_null: 907 case comparison::is_not_null:
908 case comparison::is_null: 908 case comparison::is_null:
909 { 909 {
@@ -911,7 +911,7 @@ namespace verbly {
911 } 911 }
912 } 912 }
913 } 913 }
914 914
915 case type::group: 915 case type::group:
916 { 916 {
917 std::list<binding> bindings; 917 std::list<binding> bindings;
@@ -922,30 +922,30 @@ namespace verbly {
922 bindings.push_back(std::move(value)); 922 bindings.push_back(std::move(value));
923 } 923 }
924 } 924 }
925 925
926 return bindings; 926 return bindings;
927 } 927 }
928 } 928 }
929 } 929 }
930 930
931 statement::condition::condition(bool orlogic) : type_(type::group) 931 statement::condition::condition(bool orlogic) : type_(type::group)
932 { 932 {
933 new(&group_.children_) std::list<condition>(); 933 new(&group_.children_) std::list<condition>();
934 group_.orlogic_ = orlogic; 934 group_.orlogic_ = orlogic;
935 } 935 }
936 936
937 statement::condition& statement::condition::operator+=(condition n) 937 statement::condition& statement::condition::operator+=(condition n)
938 { 938 {
939 if (type_ == type::group) 939 if (type_ == type::group)
940 { 940 {
941 group_.children_.push_back(std::move(n)); 941 group_.children_.push_back(std::move(n));
942 942
943 return *this; 943 return *this;
944 } else { 944 } else {
945 throw std::domain_error("Cannot add condition to non-group condition"); 945 throw std::domain_error("Cannot add condition to non-group condition");
946 } 946 }
947 } 947 }
948 948
949 statement::condition& statement::condition::operator&=(condition n) 949 statement::condition& statement::condition::operator&=(condition n)
950 { 950 {
951 switch (type_) 951 switch (type_)
@@ -953,32 +953,32 @@ namespace verbly {
953 case type::empty: 953 case type::empty:
954 { 954 {
955 *this = std::move(n); 955 *this = std::move(n);
956 956
957 break; 957 break;
958 } 958 }
959 959
960 case type::singleton: 960 case type::singleton:
961 { 961 {
962 condition grp(false); 962 condition grp(false);
963 grp += *this; 963 grp += *this;
964 grp += std::move(n); 964 grp += std::move(n);
965 965
966 *this = grp; 966 *this = grp;
967 967
968 break; 968 break;
969 } 969 }
970 970
971 case type::group: 971 case type::group:
972 { 972 {
973 *this += std::move(n); 973 *this += std::move(n);
974 974
975 break; 975 break;
976 } 976 }
977 } 977 }
978 978
979 return *this; 979 return *this;
980 } 980 }
981 981
982 const std::list<statement::condition>& statement::condition::getChildren() const 982 const std::list<statement::condition>& statement::condition::getChildren() const
983 { 983 {
984 if (type_ == type::group) 984 if (type_ == type::group)
@@ -988,5 +988,5 @@ namespace verbly {
988 throw std::domain_error("Cannot get children of non-group condition"); 988 throw std::domain_error("Cannot get children of non-group condition");
989 } 989 }
990 } 990 }
991 991
992}; 992};
diff --git a/lib/statement.h b/lib/statement.h index 8188ec0..aa56568 100644 --- a/lib/statement.h +++ b/lib/statement.h
@@ -11,23 +11,23 @@
11#include "filter.h" 11#include "filter.h"
12 12
13namespace verbly { 13namespace verbly {
14 14
15 class filter; 15 class filter;
16 16
17 class statement { 17 class statement {
18 public: 18 public:
19 19
20 statement(object context, filter queryFilter); 20 statement(object context, filter queryFilter);
21 21
22 std::string getQueryString(std::list<std::string> select, bool random, int limit) const; 22 std::string getQueryString(std::list<std::string> select, bool random, int limit) const;
23 23
24 std::list<binding> getBindings() const; 24 std::list<binding> getBindings() const;
25 25
26 private: 26 private:
27 27
28 class join { 28 class join {
29 public: 29 public:
30 30
31 join( 31 join(
32 bool outer, 32 bool outer,
33 std::string foreignTableName, 33 std::string foreignTableName,
@@ -43,37 +43,37 @@ namespace verbly {
43 foreignColumn_(std::move(foreignColumn)) 43 foreignColumn_(std::move(foreignColumn))
44 { 44 {
45 } 45 }
46 46
47 bool isOuterJoin() const 47 bool isOuterJoin() const
48 { 48 {
49 return outer_; 49 return outer_;
50 } 50 }
51 51
52 const std::string& getForeignTableName() const 52 const std::string& getForeignTableName() const
53 { 53 {
54 return foreignTableName_; 54 return foreignTableName_;
55 } 55 }
56 56
57 const std::string& getJoinTable() const 57 const std::string& getJoinTable() const
58 { 58 {
59 return joinTable_; 59 return joinTable_;
60 } 60 }
61 61
62 const std::string& getJoinColumn() const 62 const std::string& getJoinColumn() const
63 { 63 {
64 return joinColumn_; 64 return joinColumn_;
65 } 65 }
66 66
67 const std::string& getForeignTable() const 67 const std::string& getForeignTable() const
68 { 68 {
69 return foreignTable_; 69 return foreignTable_;
70 } 70 }
71 71
72 const std::string& getForeignColumn() const 72 const std::string& getForeignColumn() const
73 { 73 {
74 return foreignColumn_; 74 return foreignColumn_;
75 } 75 }
76 76
77 private: 77 private:
78 bool outer_ = false; 78 bool outer_ = false;
79 std::string foreignTableName_; 79 std::string foreignTableName_;
@@ -81,11 +81,11 @@ namespace verbly {
81 std::string joinColumn_; 81 std::string joinColumn_;
82 std::string foreignTable_; 82 std::string foreignTable_;
83 std::string foreignColumn_; 83 std::string foreignColumn_;
84 84
85 }; 85 };
86 86
87 friend std::ostream& operator<<(std::ostream& oss, const join& j); 87 friend std::ostream& operator<<(std::ostream& oss, const join& j);
88 88
89 class condition { 89 class condition {
90 public: 90 public:
91 enum class type { 91 enum class type {
@@ -93,7 +93,7 @@ namespace verbly {
93 singleton, 93 singleton,
94 group 94 group
95 }; 95 };
96 96
97 enum class comparison { 97 enum class comparison {
98 equals, 98 equals,
99 does_not_equal, 99 does_not_equal,
@@ -106,57 +106,57 @@ namespace verbly {
106 is_not_null, 106 is_not_null,
107 is_null 107 is_null
108 }; 108 };
109 109
110 // Copy and move constructors 110 // Copy and move constructors
111 111
112 condition(const condition& other); 112 condition(const condition& other);
113 condition(condition&& other); 113 condition(condition&& other);
114 114
115 // Assignment 115 // Assignment
116 116
117 condition& operator=(condition other); 117 condition& operator=(condition other);
118 118
119 // Swap 119 // Swap
120 120
121 friend void swap(condition& first, condition& second); 121 friend void swap(condition& first, condition& second);
122 122
123 // Destructor 123 // Destructor
124 124
125 ~condition(); 125 ~condition();
126 126
127 // Accessors 127 // Accessors
128 128
129 type getType() const 129 type getType() const
130 { 130 {
131 return type_; 131 return type_;
132 } 132 }
133 133
134 // Empty 134 // Empty
135 135
136 condition(); 136 condition();
137 137
138 // Singleton 138 // Singleton
139 139
140 condition(std::string table, std::string column, bool isNull); 140 condition(std::string table, std::string column, bool isNull);
141 141
142 condition(std::string table, std::string column, comparison comp, binding value); 142 condition(std::string table, std::string column, comparison comp, binding value);
143 143
144 // Group 144 // Group
145 145
146 explicit condition(bool orlogic); 146 explicit condition(bool orlogic);
147 147
148 condition& operator+=(condition n); 148 condition& operator+=(condition n);
149 149
150 condition& operator&=(condition n); 150 condition& operator&=(condition n);
151 151
152 const std::list<condition>& getChildren() const; 152 const std::list<condition>& getChildren() const;
153 153
154 // Utility 154 // Utility
155 155
156 std::string toSql() const; 156 std::string toSql() const;
157 157
158 std::list<binding> flattenBindings() const; 158 std::list<binding> flattenBindings() const;
159 159
160 private: 160 private:
161 union { 161 union {
162 struct { 162 struct {
@@ -172,12 +172,12 @@ namespace verbly {
172 }; 172 };
173 type type_; 173 type type_;
174 }; 174 };
175 175
176 friend void swap(condition& first, condition& second); 176 friend void swap(condition& first, condition& second);
177 177
178 class with { 178 class with {
179 public: 179 public:
180 180
181 with( 181 with(
182 std::string identifier, 182 std::string identifier,
183 field f, 183 field f,
@@ -195,42 +195,42 @@ namespace verbly {
195 recursive_(recursive) 195 recursive_(recursive)
196 { 196 {
197 } 197 }
198 198
199 const std::string& getIdentifier() const 199 const std::string& getIdentifier() const
200 { 200 {
201 return identifier_; 201 return identifier_;
202 } 202 }
203 203
204 field getField() const 204 field getField() const
205 { 205 {
206 return field_; 206 return field_;
207 } 207 }
208 208
209 std::string getTableForId(std::string identifier) const 209 std::string getTableForId(std::string identifier) const
210 { 210 {
211 return tables_.at(identifier); 211 return tables_.at(identifier);
212 } 212 }
213 213
214 const std::string& getTopTable() const 214 const std::string& getTopTable() const
215 { 215 {
216 return topTable_; 216 return topTable_;
217 } 217 }
218 218
219 const condition& getCondition() const 219 const condition& getCondition() const
220 { 220 {
221 return topCondition_; 221 return topCondition_;
222 } 222 }
223 223
224 const std::list<join>& getJoins() const 224 const std::list<join>& getJoins() const
225 { 225 {
226 return joins_; 226 return joins_;
227 } 227 }
228 228
229 bool isRecursive() const 229 bool isRecursive() const
230 { 230 {
231 return recursive_; 231 return recursive_;
232 } 232 }
233 233
234 private: 234 private:
235 std::string identifier_; 235 std::string identifier_;
236 field field_; 236 field field_;
@@ -239,9 +239,9 @@ namespace verbly {
239 condition topCondition_; 239 condition topCondition_;
240 std::list<join> joins_; 240 std::list<join> joins_;
241 bool recursive_; 241 bool recursive_;
242 242
243 }; 243 };
244 244
245 static constexpr const char* getTableForContext(object context) 245 static constexpr const char* getTableForContext(object context)
246 { 246 {
247 return (context == object::notion) ? "notions" 247 return (context == object::notion) ? "notions"
@@ -253,22 +253,22 @@ namespace verbly {
253 : (context == object::pronunciation) ? "pronunciations" 253 : (context == object::pronunciation) ? "pronunciations"
254 : throw std::domain_error("Provided context has no associated table"); 254 : throw std::domain_error("Provided context has no associated table");
255 } 255 }
256 256
257 static const std::list<field> getSelectForContext(object context); 257 static const std::list<field> getSelectForContext(object context);
258 258
259 statement(std::string tableName, filter clause, int nextTableId = 0, int nextWithId = 0); 259 statement(std::string tableName, filter clause, int nextTableId = 0, int nextWithId = 0);
260 260
261 condition parseFilter(filter queryFilter); 261 condition parseFilter(filter queryFilter);
262 262
263 std::string instantiateTable(std::string name); 263 std::string instantiateTable(std::string name);
264 264
265 std::string instantiateWith(std::string name); 265 std::string instantiateWith(std::string name);
266 266
267 condition integrate(statement subStmt, bool cte = false); 267 condition integrate(statement subStmt, bool cte = false);
268 268
269 int nextTableId_; 269 int nextTableId_;
270 int nextWithId_; 270 int nextWithId_;
271 271
272 std::map<std::string, std::string> tables_; 272 std::map<std::string, std::string> tables_;
273 std::string topTable_; 273 std::string topTable_;
274 std::list<join> joins_; 274 std::list<join> joins_;
@@ -276,7 +276,7 @@ namespace verbly {
276 condition topCondition_; 276 condition topCondition_;
277 277
278 }; 278 };
279 279
280}; 280};
281 281
282#endif /* end of include guard: STATEMENT_H_29F51659 */ 282#endif /* end of include guard: STATEMENT_H_29F51659 */
diff --git a/lib/util.h b/lib/util.h index b74b050..9db8678 100644 --- a/lib/util.h +++ b/lib/util.h
@@ -6,25 +6,25 @@
6#include <iterator> 6#include <iterator>
7 7
8namespace verbly { 8namespace verbly {
9 9
10 template <class InputIterator> 10 template <class InputIterator>
11 std::string implode(InputIterator first, InputIterator last, std::string delimiter) 11 std::string implode(InputIterator first, InputIterator last, std::string delimiter)
12 { 12 {
13 std::stringstream result; 13 std::stringstream result;
14 14
15 for (InputIterator it = first; it != last; it++) 15 for (InputIterator it = first; it != last; it++)
16 { 16 {
17 if (it != first) 17 if (it != first)
18 { 18 {
19 result << delimiter; 19 result << delimiter;
20 } 20 }
21 21
22 result << *it; 22 result << *it;
23 } 23 }
24 24
25 return result.str(); 25 return result.str();
26 } 26 }
27 27
28 template <class OutputIterator> 28 template <class OutputIterator>
29 void split(std::string input, std::string delimiter, OutputIterator out) 29 void split(std::string input, std::string delimiter, OutputIterator out)
30 { 30 {
@@ -35,27 +35,27 @@ namespace verbly {
35 { 35 {
36 *out = input; 36 *out = input;
37 out++; 37 out++;
38 38
39 input = ""; 39 input = "";
40 } else { 40 } else {
41 *out = input.substr(0, divider); 41 *out = input.substr(0, divider);
42 out++; 42 out++;
43 43
44 input = input.substr(divider+delimiter.length()); 44 input = input.substr(divider+delimiter.length());
45 } 45 }
46 } 46 }
47 } 47 }
48 48
49 template <class Container> 49 template <class Container>
50 Container split(std::string input, std::string delimiter) 50 Container split(std::string input, std::string delimiter)
51 { 51 {
52 Container result; 52 Container result;
53 53
54 split(input, delimiter, std::back_inserter(result)); 54 split(input, delimiter, std::back_inserter(result));
55 55
56 return result; 56 return result;
57 } 57 }
58 58
59}; 59};
60 60
61#endif /* end of include guard: UTIL_H_15DDCA2D */ 61#endif /* end of include guard: UTIL_H_15DDCA2D */
diff --git a/lib/word.cpp b/lib/word.cpp index d13d0bc..a928659 100644 --- a/lib/word.cpp +++ b/lib/word.cpp
@@ -6,118 +6,118 @@
6#include "query.h" 6#include "query.h"
7 7
8namespace verbly { 8namespace verbly {
9 9
10 const object word::objectType = object::word; 10 const object word::objectType = object::word;
11 11
12 const std::list<std::string> word::select = {"word_id", "notion_id", "lemma_id", "tag_count", "position", "group_id"}; 12 const std::list<std::string> word::select = {"word_id", "notion_id", "lemma_id", "tag_count", "position", "group_id"};
13 13
14 const field word::id = field::integerField(object::word, "word_id"); 14 const field word::id = field::integerField(object::word, "word_id");
15 const field word::tagCount = field::integerField(object::word, "tag_count", true); 15 const field word::tagCount = field::integerField(object::word, "tag_count", true);
16 const field word::adjectivePosition = field::integerField(object::word, "position", true); 16 const field word::adjectivePosition = field::integerField(object::word, "position", true);
17 17
18 const field word::notion = field::joinField(object::word, "notion_id", object::notion); 18 const field word::notion = field::joinField(object::word, "notion_id", object::notion);
19 const field word::lemma = field::joinField(object::word, "lemma_id", object::lemma); 19 const field word::lemma = field::joinField(object::word, "lemma_id", object::lemma);
20 const field word::group = field::joinField(object::word, "group_id", object::group, true); 20 const field word::group = field::joinField(object::word, "group_id", object::group, true);
21 21
22 const field word::antonyms = field::selfJoin(object::word, "word_id", "antonymy", "antonym_2_id", "antonym_1_id"); 22 const field word::antonyms = field::selfJoin(object::word, "word_id", "antonymy", "antonym_2_id", "antonym_1_id");
23 23
24 const field word::specifications = field::selfJoin(object::word, "word_id", "specification", "general_id", "specific_id"); 24 const field word::specifications = field::selfJoin(object::word, "word_id", "specification", "general_id", "specific_id");
25 const field word::generalizations = field::selfJoin(object::word, "word_id", "specification", "specific_id", "general_id"); 25 const field word::generalizations = field::selfJoin(object::word, "word_id", "specification", "specific_id", "general_id");
26 26
27 const field word::pertainyms = field::selfJoin(object::word, "word_id", "pertainymy", "noun_id", "pertainym_id"); 27 const field word::pertainyms = field::selfJoin(object::word, "word_id", "pertainymy", "noun_id", "pertainym_id");
28 const field word::antiPertainyms = field::selfJoin(object::word, "word_id", "pertainymy", "pertainym_id", "noun_id"); 28 const field word::antiPertainyms = field::selfJoin(object::word, "word_id", "pertainymy", "pertainym_id", "noun_id");
29 29
30 const field word::mannernyms = field::selfJoin(object::word, "word_id", "mannernymy", "adjective_id", "mannernym_id"); 30 const field word::mannernyms = field::selfJoin(object::word, "word_id", "mannernymy", "adjective_id", "mannernym_id");
31 const field word::antiMannernyms = field::selfJoin(object::word, "word_id", "mannernymy", "mannernym_id", "adjective_id"); 31 const field word::antiMannernyms = field::selfJoin(object::word, "word_id", "mannernymy", "mannernym_id", "adjective_id");
32 32
33 const field word::usageTerms = field::selfJoin(object::word, "word_id", "usage", "domain_id", "term_id"); 33 const field word::usageTerms = field::selfJoin(object::word, "word_id", "usage", "domain_id", "term_id");
34 const field word::usageDomains = field::selfJoin(object::word, "word_id", "usage", "term_id", "domain_id"); 34 const field word::usageDomains = field::selfJoin(object::word, "word_id", "usage", "term_id", "domain_id");
35 35
36 const field word::topicalTerms = field::selfJoin(object::word, "word_id", "topicality", "domain_id", "term_id"); 36 const field word::topicalTerms = field::selfJoin(object::word, "word_id", "topicality", "domain_id", "term_id");
37 const field word::topicalDomains = field::selfJoin(object::word, "word_id", "topicality", "term_id", "domain_id"); 37 const field word::topicalDomains = field::selfJoin(object::word, "word_id", "topicality", "term_id", "domain_id");
38 38
39 const field word::regionalTerms = field::selfJoin(object::word, "word_id", "regionality", "domain_id", "term_id"); 39 const field word::regionalTerms = field::selfJoin(object::word, "word_id", "regionality", "domain_id", "term_id");
40 const field word::regionalDomains = field::selfJoin(object::word, "word_id", "regionality", "term_id", "domain_id"); 40 const field word::regionalDomains = field::selfJoin(object::word, "word_id", "regionality", "term_id", "domain_id");
41 41
42 word::word(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) 42 word::word(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true)
43 { 43 {
44 id_ = sqlite3_column_int(row, 0); 44 id_ = sqlite3_column_int(row, 0);
45 notionId_ = sqlite3_column_int(row, 1); 45 notionId_ = sqlite3_column_int(row, 1);
46 lemmaId_ = sqlite3_column_int(row, 2); 46 lemmaId_ = sqlite3_column_int(row, 2);
47 47
48 if (sqlite3_column_type(row, 3) != SQLITE_NULL) 48 if (sqlite3_column_type(row, 3) != SQLITE_NULL)
49 { 49 {
50 hasTagCount_ = true; 50 hasTagCount_ = true;
51 tagCount_ = sqlite3_column_int(row, 3); 51 tagCount_ = sqlite3_column_int(row, 3);
52 } 52 }
53 53
54 if (sqlite3_column_type(row, 4) != SQLITE_NULL) 54 if (sqlite3_column_type(row, 4) != SQLITE_NULL)
55 { 55 {
56 adjectivePosition_ = static_cast<positioning>(sqlite3_column_int(row, 4)); 56 adjectivePosition_ = static_cast<positioning>(sqlite3_column_int(row, 4));
57 } 57 }
58 58
59 if (sqlite3_column_type(row, 5) != SQLITE_NULL) 59 if (sqlite3_column_type(row, 5) != SQLITE_NULL)
60 { 60 {
61 hasGroup_ = true; 61 hasGroup_ = true;
62 groupId_ = sqlite3_column_int(row, 5); 62 groupId_ = sqlite3_column_int(row, 5);
63 } 63 }
64 } 64 }
65 65
66 const notion& word::getNotion() const 66 const notion& word::getNotion() const
67 { 67 {
68 if (!valid_) 68 if (!valid_)
69 { 69 {
70 throw std::domain_error("Bad access to uninitialized word"); 70 throw std::domain_error("Bad access to uninitialized word");
71 } 71 }
72 72
73 if (!notion_) 73 if (!notion_)
74 { 74 {
75 notion_ = db_->notions(notion::id == notionId_).first(); 75 notion_ = db_->notions(notion::id == notionId_).first();
76 } 76 }
77 77
78 return notion_; 78 return notion_;
79 } 79 }
80 80
81 const lemma& word::getLemma() const 81 const lemma& word::getLemma() const
82 { 82 {
83 if (!valid_) 83 if (!valid_)
84 { 84 {
85 throw std::domain_error("Bad access to uninitialized word"); 85 throw std::domain_error("Bad access to uninitialized word");
86 } 86 }
87 87
88 if (!lemma_) 88 if (!lemma_)
89 { 89 {
90 lemma_ = db_->lemmas(lemma::id == lemmaId_).first(); 90 lemma_ = db_->lemmas(lemma::id == lemmaId_).first();
91 } 91 }
92 92
93 return lemma_; 93 return lemma_;
94 } 94 }
95 95
96 const group& word::getGroup() const 96 const group& word::getGroup() const
97 { 97 {
98 if (!valid_) 98 if (!valid_)
99 { 99 {
100 throw std::domain_error("Bad access to uninitialized word"); 100 throw std::domain_error("Bad access to uninitialized word");
101 } 101 }
102 102
103 if (!hasGroup_) 103 if (!hasGroup_)
104 { 104 {
105 throw std::domain_error("Word does not have a group"); 105 throw std::domain_error("Word does not have a group");
106 } 106 }
107 107
108 if (!group_) 108 if (!group_)
109 { 109 {
110 group_ = db_->groups(group::id == groupId_).first(); 110 group_ = db_->groups(group::id == groupId_).first();
111 } 111 }
112 112
113 return group_; 113 return group_;
114 } 114 }
115 115
116 std::string word::getBaseForm() const 116 std::string word::getBaseForm() const
117 { 117 {
118 return getLemma().getBaseForm().getText(); 118 return getLemma().getBaseForm().getText();
119 } 119 }
120 120
121 std::vector<std::string> word::getInflections(inflection category) const 121 std::vector<std::string> word::getInflections(inflection category) const
122 { 122 {
123 std::vector<std::string> result; 123 std::vector<std::string> result;
@@ -128,5 +128,5 @@ namespace verbly {
128 128
129 return result; 129 return result;
130 } 130 }
131 131
132}; 132};
diff --git a/lib/word.h b/lib/word.h index 7b3c0f7..ddcabe4 100644 --- a/lib/word.h +++ b/lib/word.h
@@ -12,157 +12,157 @@
12struct sqlite3_stmt; 12struct sqlite3_stmt;
13 13
14namespace verbly { 14namespace verbly {
15 15
16 class database; 16 class database;
17 17
18 class word { 18 class word {
19 public: 19 public:
20 20
21 // Default constructor 21 // Default constructor
22 22
23 word() = default; 23 word() = default;
24 24
25 // Construct from database 25 // Construct from database
26 26
27 word(const database& db, sqlite3_stmt* row); 27 word(const database& db, sqlite3_stmt* row);
28 28
29 // Accessors 29 // Accessors
30 30
31 operator bool() const 31 operator bool() const
32 { 32 {
33 return valid_; 33 return valid_;
34 } 34 }
35 35
36 int getId() const 36 int getId() const
37 { 37 {
38 if (!valid_) 38 if (!valid_)
39 { 39 {
40 throw std::domain_error("Bad access to uninitialized word"); 40 throw std::domain_error("Bad access to uninitialized word");
41 } 41 }
42 42
43 return id_; 43 return id_;
44 } 44 }
45 45
46 bool hasTagCount() const 46 bool hasTagCount() const
47 { 47 {
48 if (!valid_) 48 if (!valid_)
49 { 49 {
50 throw std::domain_error("Bad access to uninitialized word"); 50 throw std::domain_error("Bad access to uninitialized word");
51 } 51 }
52 52
53 return hasTagCount_; 53 return hasTagCount_;
54 } 54 }
55 55
56 int getTagCount() const 56 int getTagCount() const
57 { 57 {
58 if (!valid_) 58 if (!valid_)
59 { 59 {
60 throw std::domain_error("Bad access to uninitialized word"); 60 throw std::domain_error("Bad access to uninitialized word");
61 } 61 }
62 62
63 if (!hasTagCount_) 63 if (!hasTagCount_)
64 { 64 {
65 throw std::domain_error("Word has no tag count"); 65 throw std::domain_error("Word has no tag count");
66 } 66 }
67 67
68 return tagCount_; 68 return tagCount_;
69 } 69 }
70 70
71 bool hasAdjectivePositioning() const 71 bool hasAdjectivePositioning() const
72 { 72 {
73 if (!valid_) 73 if (!valid_)
74 { 74 {
75 throw std::domain_error("Bad access to uninitialized word"); 75 throw std::domain_error("Bad access to uninitialized word");
76 } 76 }
77 77
78 return (adjectivePosition_ != positioning::undefined); 78 return (adjectivePosition_ != positioning::undefined);
79 } 79 }
80 80
81 positioning getAdjectivePosition() const 81 positioning getAdjectivePosition() const
82 { 82 {
83 if (!valid_) 83 if (!valid_)
84 { 84 {
85 throw std::domain_error("Bad access to uninitialized word"); 85 throw std::domain_error("Bad access to uninitialized word");
86 } 86 }
87 87
88 if (adjectivePosition_ == positioning::undefined) 88 if (adjectivePosition_ == positioning::undefined)
89 { 89 {
90 throw std::domain_error("Word has no adjective position"); 90 throw std::domain_error("Word has no adjective position");
91 } 91 }
92 92
93 return adjectivePosition_; 93 return adjectivePosition_;
94 } 94 }
95 95
96 const notion& getNotion() const; 96 const notion& getNotion() const;
97 97
98 const lemma& getLemma() const; 98 const lemma& getLemma() const;
99 99
100 bool hasGroup() const 100 bool hasGroup() const
101 { 101 {
102 if (!valid_) 102 if (!valid_)
103 { 103 {
104 throw std::domain_error("Bad access to uninitialized word"); 104 throw std::domain_error("Bad access to uninitialized word");
105 } 105 }
106 106
107 return hasGroup_; 107 return hasGroup_;
108 } 108 }
109 109
110 const group& getGroup() const; 110 const group& getGroup() const;
111 111
112 // Convenience accessors 112 // Convenience accessors
113 113
114 std::string getBaseForm() const; 114 std::string getBaseForm() const;
115 115
116 std::vector<std::string> getInflections(inflection infl) const; 116 std::vector<std::string> getInflections(inflection infl) const;
117 117
118 // Type info 118 // Type info
119 119
120 static const object objectType; 120 static const object objectType;
121 121
122 static const std::list<std::string> select; 122 static const std::list<std::string> select;
123 123
124 // Query fields 124 // Query fields
125 125
126 static const field id; 126 static const field id;
127 static const field tagCount; 127 static const field tagCount;
128 static const field adjectivePosition; 128 static const field adjectivePosition;
129 129
130 operator filter() const 130 operator filter() const
131 { 131 {
132 return (id == id_); 132 return (id == id_);
133 } 133 }
134 134
135 // Relationships with other objects 135 // Relationships with other objects
136 136
137 static const field notion; 137 static const field notion;
138 static const field lemma; 138 static const field lemma;
139 static const field group; 139 static const field group;
140 140
141 // Relationships with self 141 // Relationships with self
142 142
143 static const field antonyms; 143 static const field antonyms;
144 144
145 static const field specifications; 145 static const field specifications;
146 static const field generalizations; 146 static const field generalizations;
147 147
148 static const field pertainyms; 148 static const field pertainyms;
149 static const field antiPertainyms; 149 static const field antiPertainyms;
150 150
151 static const field mannernyms; 151 static const field mannernyms;
152 static const field antiMannernyms; 152 static const field antiMannernyms;
153 153
154 static const field usageTerms; 154 static const field usageTerms;
155 static const field usageDomains; 155 static const field usageDomains;
156 156
157 static const field topicalTerms; 157 static const field topicalTerms;
158 static const field topicalDomains; 158 static const field topicalDomains;
159 159
160 static const field regionalTerms; 160 static const field regionalTerms;
161 static const field regionalDomains; 161 static const field regionalDomains;
162 162
163 private: 163 private:
164 bool valid_ = false; 164 bool valid_ = false;
165 165
166 int id_; 166 int id_;
167 bool hasTagCount_ = false; 167 bool hasTagCount_ = false;
168 int tagCount_; 168 int tagCount_;
@@ -171,15 +171,15 @@ namespace verbly {
171 int lemmaId_; 171 int lemmaId_;
172 bool hasGroup_ = false; 172 bool hasGroup_ = false;
173 int groupId_; 173 int groupId_;
174 174
175 const database* db_; 175 const database* db_;
176 176
177 mutable class notion notion_; 177 mutable class notion notion_;
178 mutable class lemma lemma_; 178 mutable class lemma lemma_;
179 mutable class group group_; 179 mutable class group group_;
180 180
181 }; 181 };
182 182
183}; 183};
184 184
185#endif /* end of include guard: WORD_H_DF91B1B4 */ 185#endif /* end of include guard: WORD_H_DF91B1B4 */