summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2017-01-24 17:44:08 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2017-01-24 17:44:08 -0500
commit6112294292fbe5700b9b652dea54a8e6c6f1c172 (patch)
tree6df053f7e3f0db07ca433bb532b852317f005673
parenta5782a2133bae494e6c4ba3b4c2840aedab1da21 (diff)
downloadverbly-6112294292fbe5700b9b652dea54a8e6c6f1c172.tar.gz
verbly-6112294292fbe5700b9b652dea54a8e6c6f1c172.tar.bz2
verbly-6112294292fbe5700b9b652dea54a8e6c6f1c172.zip
Fixed behavior of normalizing grouped hierarchal joins
Previously, we did not merge grouped hierarchal joins; however, because
of the way statements are compiled, we do need to merge OR-d positive
hierarchal joins, and ANDed negative hierarchal joins.

Also made some whitespace changes.
-rw-r--r--lib/field.h107
-rw-r--r--lib/filter.cpp32
2 files changed, 82 insertions, 57 deletions
diff --git a/lib/field.h b/lib/field.h index 30c62be..f61e038 100644 --- a/lib/field.h +++ b/lib/field.h
@@ -6,9 +6,9 @@
6#include <tuple> 6#include <tuple>
7 7
8namespace verbly { 8namespace verbly {
9 9
10 class filter; 10 class filter;
11 11
12 class field { 12 class field {
13 public: 13 public:
14 enum class type { 14 enum class type {
@@ -20,15 +20,15 @@ namespace verbly {
20 join_through, 20 join_through,
21 hierarchal_join 21 hierarchal_join
22 }; 22 };
23 23
24 // Default constructor 24 // Default constructor
25 25
26 field() 26 field()
27 { 27 {
28 } 28 }
29 29
30 // Static factories 30 // Static factories
31 31
32 static field stringField( 32 static field stringField(
33 object obj, 33 object obj,
34 const char* name, 34 const char* name,
@@ -36,7 +36,7 @@ namespace verbly {
36 { 36 {
37 return field(obj, type::string, name, nullable); 37 return field(obj, type::string, name, nullable);
38 } 38 }
39 39
40 static field stringField( 40 static field stringField(
41 const char* table, 41 const char* table,
42 const char* name, 42 const char* name,
@@ -44,7 +44,7 @@ namespace verbly {
44 { 44 {
45 return field(object::undefined, type::string, name, nullable, table); 45 return field(object::undefined, type::string, name, nullable, table);
46 } 46 }
47 47
48 static field integerField( 48 static field integerField(
49 object obj, 49 object obj,
50 const char* name, 50 const char* name,
@@ -52,7 +52,7 @@ namespace verbly {
52 { 52 {
53 return field(obj, type::integer, name, nullable); 53 return field(obj, type::integer, name, nullable);
54 } 54 }
55 55
56 static field integerField( 56 static field integerField(
57 const char* table, 57 const char* table,
58 const char* name, 58 const char* name,
@@ -60,7 +60,7 @@ namespace verbly {
60 { 60 {
61 return field(object::undefined, type::integer, name, nullable, table); 61 return field(object::undefined, type::integer, name, nullable, table);
62 } 62 }
63 63
64 static field booleanField( 64 static field booleanField(
65 object obj, 65 object obj,
66 const char* name, 66 const char* name,
@@ -68,7 +68,7 @@ namespace verbly {
68 { 68 {
69 return field(obj, type::boolean, name, nullable); 69 return field(obj, type::boolean, name, nullable);
70 } 70 }
71 71
72 static field booleanField( 72 static field booleanField(
73 const char* table, 73 const char* table,
74 const char* name, 74 const char* name,
@@ -76,7 +76,7 @@ namespace verbly {
76 { 76 {
77 return field(object::undefined, type::boolean, name, nullable, table); 77 return field(object::undefined, type::boolean, name, nullable, table);
78 } 78 }
79 79
80 static field joinField( 80 static field joinField(
81 object obj, 81 object obj,
82 const char* name, 82 const char* name,
@@ -85,7 +85,7 @@ namespace verbly {
85 { 85 {
86 return field(obj, type::join, name, nullable, 0, joinWith); 86 return field(obj, type::join, name, nullable, 0, joinWith);
87 } 87 }
88 88
89 static field joinField( 89 static field joinField(
90 object obj, 90 object obj,
91 const char* name, 91 const char* name,
@@ -94,7 +94,7 @@ namespace verbly {
94 { 94 {
95 return field(obj, type::join, name, nullable, table); 95 return field(obj, type::join, name, nullable, table);
96 } 96 }
97 97
98 static field joinThrough( 98 static field joinThrough(
99 object obj, 99 object obj,
100 const char* name, 100 const char* name,
@@ -104,7 +104,7 @@ namespace verbly {
104 { 104 {
105 return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, name, foreignColumn); 105 return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, name, foreignColumn);
106 } 106 }
107 107
108 static field joinThrough( 108 static field joinThrough(
109 object obj, 109 object obj,
110 const char* name, 110 const char* name,
@@ -116,7 +116,7 @@ namespace verbly {
116 { 116 {
117 return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, joinColumn, foreignJoinColumn); 117 return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, joinColumn, foreignJoinColumn);
118 } 118 }
119 119
120 static field selfJoin( 120 static field selfJoin(
121 object obj, 121 object obj,
122 const char* name, 122 const char* name,
@@ -126,7 +126,7 @@ namespace verbly {
126 { 126 {
127 return field(obj, type::join_through, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn); 127 return field(obj, type::join_through, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn);
128 } 128 }
129 129
130 static field hierarchalSelfJoin( 130 static field hierarchalSelfJoin(
131 object obj, 131 object obj,
132 const char* name, 132 const char* name,
@@ -136,56 +136,57 @@ namespace verbly {
136 { 136 {
137 return field(obj, type::hierarchal_join, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn); 137 return field(obj, type::hierarchal_join, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn);
138 } 138 }
139 139
140 // Accessors 140 // Accessors
141 141
142 object getObject() const 142 object getObject() const
143 { 143 {
144 return object_; 144 return object_;
145 } 145 }
146 146
147 type getType() const 147 type getType() const
148 { 148 {
149 return type_; 149 return type_;
150 } 150 }
151 151
152 bool isJoin() const 152 bool isJoin() const
153 { 153 {
154 return ((type_ == type::join) || (type_ == type::join_through) || (type_ == type::hierarchal_join)); 154 return ((type_ == type::join) || (type_ == type::join_through) || (type_ == type::hierarchal_join));
155 } 155 }
156 156
157 const char* getColumn() const 157 const char* getColumn() const
158 { 158 {
159 return column_; 159 return column_;
160 } 160 }
161 161
162 bool isNullable() const 162 bool isNullable() const
163 { 163 {
164 return nullable_; 164 return nullable_;
165 } 165 }
166 166
167 bool hasTable() const 167 bool hasTable() const
168 { 168 {
169 return (table_ != 0); 169 return (table_ != 0);
170 } 170 }
171 171
172 const char* getTable() const 172 const char* getTable() const
173 { 173 {
174 return table_; 174 return table_;
175 } 175 }
176 176
177 // Joins 177 // Joins
178 178
179 object getJoinObject() const 179 object getJoinObject() const
180 { 180 {
181 // We ignore hierarchal joins because they are always self joins. 181 return (type_ == type::hierarchal_join)
182 return ((type_ == type::join) || (type_ == type::join_through)) 182 ? object_
183 : ((type_ == type::join) || (type_ == type::join_through))
183 ? joinObject_ 184 ? joinObject_
184 : throw std::domain_error("Non-join fields don't have join objects"); 185 : throw std::domain_error("Non-join fields don't have join objects");
185 } 186 }
186 187
187 // Many-to-many joins 188 // Many-to-many joins
188 189
189 const char* getForeignColumn() const 190 const char* getForeignColumn() const
190 { 191 {
191 // We ignore hierarchal joins because they are always self joins. 192 // We ignore hierarchal joins because they are always self joins.
@@ -193,23 +194,23 @@ namespace verbly {
193 ? foreignColumn_ 194 ? foreignColumn_
194 : throw std::domain_error("Only many-to-many join fields have a foreign column"); 195 : throw std::domain_error("Only many-to-many join fields have a foreign column");
195 } 196 }
196 197
197 const char* getJoinColumn() const 198 const char* getJoinColumn() const
198 { 199 {
199 return ((type_ == type::join_through) || (type_ == type::hierarchal_join)) 200 return ((type_ == type::join_through) || (type_ == type::hierarchal_join))
200 ? joinColumn_ 201 ? joinColumn_
201 : throw std::domain_error("Only many-to-many join fields have a join column"); 202 : throw std::domain_error("Only many-to-many join fields have a join column");
202 } 203 }
203 204
204 const char* getForeignJoinColumn() const 205 const char* getForeignJoinColumn() const
205 { 206 {
206 return ((type_ == type::join_through) || (type_ == type::hierarchal_join)) 207 return ((type_ == type::join_through) || (type_ == type::hierarchal_join))
207 ? foreignJoinColumn_ 208 ? foreignJoinColumn_
208 : throw std::domain_error("Only many-to-many join fields have a foreign join column"); 209 : throw std::domain_error("Only many-to-many join fields have a foreign join column");
209 } 210 }
210 211
211 // Ordering 212 // Ordering
212 213
213 bool operator<(const field& other) const 214 bool operator<(const field& other) const
214 { 215 {
215 // For the most part, (object, column) uniquely identifies fields. 216 // For the most part, (object, column) uniquely identifies fields.
@@ -219,9 +220,9 @@ namespace verbly {
219 // table (hypernymy); however, they have different join columns. 220 // table (hypernymy); however, they have different join columns.
220 return std::tie(object_, column_, table_, joinColumn_) < std::tie(other.object_, other.column_, other.table_, other.joinColumn_); 221 return std::tie(object_, column_, table_, joinColumn_) < std::tie(other.object_, other.column_, other.table_, other.joinColumn_);
221 } 222 }
222 223
223 // Equality 224 // Equality
224 225
225 bool operator==(const field& other) const 226 bool operator==(const field& other) const
226 { 227 {
227 // For the most part, (object, column) uniquely identifies fields. 228 // For the most part, (object, column) uniquely identifies fields.
@@ -231,35 +232,35 @@ namespace verbly {
231 // table (hypernymy); however, they have different join columns. 232 // table (hypernymy); however, they have different join columns.
232 return std::tie(object_, column_, table_, joinColumn_) == std::tie(other.object_, other.column_, other.table_, other.joinColumn_); 233 return std::tie(object_, column_, table_, joinColumn_) == std::tie(other.object_, other.column_, other.table_, other.joinColumn_);
233 } 234 }
234 235
235 // Filter construction 236 // Filter construction
236 237
237 filter operator==(int value) const; // Integer equality 238 filter operator==(int value) const; // Integer equality
238 filter operator!=(int value) const; // Integer inequality 239 filter operator!=(int value) const; // Integer inequality
239 filter operator<(int value) const; // Integer is less than 240 filter operator<(int value) const; // Integer is less than
240 filter operator<=(int value) const; // Integer is at most 241 filter operator<=(int value) const; // Integer is at most
241 filter operator>(int value) const; // Integer is greater than 242 filter operator>(int value) const; // Integer is greater than
242 filter operator>=(int value) const; // Integer is at least 243 filter operator>=(int value) const; // Integer is at least
243 244
244 filter operator==(part_of_speech value) const; // Part of speech equality 245 filter operator==(part_of_speech value) const; // Part of speech equality
245 filter operator==(positioning value) const; // Adjective positioning equality 246 filter operator==(positioning value) const; // Adjective positioning equality
246 filter operator==(inflection value) const; // Inflection category equality 247 filter operator==(inflection value) const; // Inflection category equality
247 248
248 filter operator==(bool value) const; // Boolean equality 249 filter operator==(bool value) const; // Boolean equality
249 250
250 filter operator==(std::string value) const; // String equality 251 filter operator==(std::string value) const; // String equality
251 filter operator!=(std::string value) const; // String inequality 252 filter operator!=(std::string value) const; // String inequality
252 filter operator%=(std::string value) const; // String matching 253 filter operator%=(std::string value) const; // String matching
253 254
254 operator filter() const; // Non-nullity 255 operator filter() const; // Non-nullity
255 filter operator!() const; // Nullity 256 filter operator!() const; // Nullity
256 257
257 filter operator%=(filter joinCondition) const; // Join 258 filter operator%=(filter joinCondition) const; // Join
258 259
259 private: 260 private:
260 261
261 // Constructor 262 // Constructor
262 263
263 field( 264 field(
264 object obj, 265 object obj,
265 type datatype, 266 type datatype,
@@ -281,26 +282,26 @@ namespace verbly {
281 foreignJoinColumn_(foreignJoinColumn) 282 foreignJoinColumn_(foreignJoinColumn)
282 { 283 {
283 } 284 }
284 285
285 // General 286 // General
286 object object_ = object::undefined; 287 object object_ = object::undefined;
287 type type_ = type::undefined; 288 type type_ = type::undefined;
288 const char* column_ = 0; 289 const char* column_ = 0;
289 const char* table_ = 0; 290 const char* table_ = 0;
290 291
291 // Non-joins and belongs-to joins 292 // Non-joins and belongs-to joins
292 bool nullable_ = false; 293 bool nullable_ = false;
293 294
294 // Joins 295 // Joins
295 object joinObject_ = object::undefined; 296 object joinObject_ = object::undefined;
296 297
297 // Many-to-many joins 298 // Many-to-many joins
298 const char* foreignColumn_ = 0; 299 const char* foreignColumn_ = 0;
299 const char* joinColumn_ = 0; 300 const char* joinColumn_ = 0;
300 const char* foreignJoinColumn_ = 0; 301 const char* foreignJoinColumn_ = 0;
301 302
302 }; 303 };
303 304
304}; 305};
305 306
306#endif /* end of include guard: FIELD_H_43258321 */ 307#endif /* end of include guard: FIELD_H_43258321 */
diff --git a/lib/filter.cpp b/lib/filter.cpp index 17309f1..ceb9327 100644 --- a/lib/filter.cpp +++ b/lib/filter.cpp
@@ -1283,7 +1283,9 @@ namespace verbly {
1283 { 1283 {
1284 filter normalized = child.normalize(context); 1284 filter normalized = child.normalize(context);
1285 1285
1286 // Notably, this does not attempt to merge hierarchal matches. 1286 // Notably, this does not attempt to merge hierarchal matches,
1287 // UNLESS they are positive matches being OR-d, or negative
1288 // matches being ANDed.
1287 switch (normalized.getType()) 1289 switch (normalized.getType())
1288 { 1290 {
1289 case type::singleton: 1291 case type::singleton:
@@ -1306,7 +1308,7 @@ namespace verbly {
1306 { 1308 {
1307 if (!negativeJoins.count(normalized.singleton_.filterField)) 1309 if (!negativeJoins.count(normalized.singleton_.filterField))
1308 { 1310 {
1309 negativeJoins[normalized.getField()] = filter(group_.orlogic); 1311 negativeJoins[normalized.getField()] = filter(!group_.orlogic);
1310 } 1312 }
1311 1313
1312 negativeJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join); 1314 negativeJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join);
@@ -1314,6 +1316,30 @@ namespace verbly {
1314 break; 1316 break;
1315 } 1317 }
1316 1318
1319 case comparison::hierarchally_matches:
1320 {
1321 if (group_.orlogic)
1322 {
1323 positiveJoins[normalized.getField()] |= std::move(*normalized.singleton_.join);
1324 } else {
1325 result += std::move(normalized);
1326 }
1327
1328 break;
1329 }
1330
1331 case comparison::does_not_hierarchally_match:
1332 {
1333 if (!group_.orlogic)
1334 {
1335 negativeJoins[normalized.getField()] |= std::move(*normalized.singleton_.join);
1336 } else {
1337 result += std::move(normalized);
1338 }
1339
1340 break;
1341 }
1342
1317 case comparison::int_equals: 1343 case comparison::int_equals:
1318 case comparison::int_does_not_equal: 1344 case comparison::int_does_not_equal:
1319 case comparison::int_is_at_least: 1345 case comparison::int_is_at_least:
@@ -1327,8 +1353,6 @@ namespace verbly {
1327 case comparison::string_is_not_like: 1353 case comparison::string_is_not_like:
1328 case comparison::is_null: 1354 case comparison::is_null:
1329 case comparison::is_not_null: 1355 case comparison::is_not_null:
1330 case comparison::hierarchally_matches:
1331 case comparison::does_not_hierarchally_match:
1332 { 1356 {
1333 result += std::move(normalized); 1357 result += std::move(normalized);
1334 1358