diff options
| -rw-r--r-- | lib/field.h | 107 | ||||
| -rw-r--r-- | lib/filter.cpp | 32 |
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 | ||
| 8 | namespace verbly { | 8 | namespace 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 | ||
