From 6112294292fbe5700b9b652dea54a8e6c6f1c172 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 24 Jan 2017 17:44:08 -0500 Subject: 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. --- lib/field.h | 107 +++++++++++++++++++++++++++++---------------------------- 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 @@ #include namespace verbly { - + class filter; - + class field { public: enum class type { @@ -20,15 +20,15 @@ namespace verbly { join_through, hierarchal_join }; - + // Default constructor - + field() { } - + // Static factories - + static field stringField( object obj, const char* name, @@ -36,7 +36,7 @@ namespace verbly { { return field(obj, type::string, name, nullable); } - + static field stringField( const char* table, const char* name, @@ -44,7 +44,7 @@ namespace verbly { { return field(object::undefined, type::string, name, nullable, table); } - + static field integerField( object obj, const char* name, @@ -52,7 +52,7 @@ namespace verbly { { return field(obj, type::integer, name, nullable); } - + static field integerField( const char* table, const char* name, @@ -60,7 +60,7 @@ namespace verbly { { return field(object::undefined, type::integer, name, nullable, table); } - + static field booleanField( object obj, const char* name, @@ -68,7 +68,7 @@ namespace verbly { { return field(obj, type::boolean, name, nullable); } - + static field booleanField( const char* table, const char* name, @@ -76,7 +76,7 @@ namespace verbly { { return field(object::undefined, type::boolean, name, nullable, table); } - + static field joinField( object obj, const char* name, @@ -85,7 +85,7 @@ namespace verbly { { return field(obj, type::join, name, nullable, 0, joinWith); } - + static field joinField( object obj, const char* name, @@ -94,7 +94,7 @@ namespace verbly { { return field(obj, type::join, name, nullable, table); } - + static field joinThrough( object obj, const char* name, @@ -104,7 +104,7 @@ namespace verbly { { return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, name, foreignColumn); } - + static field joinThrough( object obj, const char* name, @@ -116,7 +116,7 @@ namespace verbly { { return field(obj, type::join_through, name, true, joinTable, joinWith, foreignColumn, joinColumn, foreignJoinColumn); } - + static field selfJoin( object obj, const char* name, @@ -126,7 +126,7 @@ namespace verbly { { return field(obj, type::join_through, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn); } - + static field hierarchalSelfJoin( object obj, const char* name, @@ -136,56 +136,57 @@ namespace verbly { { return field(obj, type::hierarchal_join, name, true, joinTable, obj, name, joinColumn, foreignJoinColumn); } - + // Accessors - + object getObject() const { return object_; } - + type getType() const { return type_; } - + bool isJoin() const { return ((type_ == type::join) || (type_ == type::join_through) || (type_ == type::hierarchal_join)); } - + const char* getColumn() const { return column_; } - + bool isNullable() const { return nullable_; } - + bool hasTable() const { return (table_ != 0); } - + const char* getTable() const { return table_; } - + // Joins - + object getJoinObject() const { - // We ignore hierarchal joins because they are always self joins. - return ((type_ == type::join) || (type_ == type::join_through)) + return (type_ == type::hierarchal_join) + ? object_ + : ((type_ == type::join) || (type_ == type::join_through)) ? joinObject_ : throw std::domain_error("Non-join fields don't have join objects"); } - + // Many-to-many joins - + const char* getForeignColumn() const { // We ignore hierarchal joins because they are always self joins. @@ -193,23 +194,23 @@ namespace verbly { ? foreignColumn_ : throw std::domain_error("Only many-to-many join fields have a foreign column"); } - + const char* getJoinColumn() const { return ((type_ == type::join_through) || (type_ == type::hierarchal_join)) ? joinColumn_ : throw std::domain_error("Only many-to-many join fields have a join column"); } - + const char* getForeignJoinColumn() const { return ((type_ == type::join_through) || (type_ == type::hierarchal_join)) ? foreignJoinColumn_ : throw std::domain_error("Only many-to-many join fields have a foreign join column"); } - + // Ordering - + bool operator<(const field& other) const { // For the most part, (object, column) uniquely identifies fields. @@ -219,9 +220,9 @@ namespace verbly { // table (hypernymy); however, they have different join columns. return std::tie(object_, column_, table_, joinColumn_) < std::tie(other.object_, other.column_, other.table_, other.joinColumn_); } - + // Equality - + bool operator==(const field& other) const { // For the most part, (object, column) uniquely identifies fields. @@ -231,35 +232,35 @@ namespace verbly { // table (hypernymy); however, they have different join columns. return std::tie(object_, column_, table_, joinColumn_) == std::tie(other.object_, other.column_, other.table_, other.joinColumn_); } - + // Filter construction - + filter operator==(int value) const; // Integer equality filter operator!=(int value) const; // Integer inequality filter operator<(int value) const; // Integer is less than filter operator<=(int value) const; // Integer is at most filter operator>(int value) const; // Integer is greater than filter operator>=(int value) const; // Integer is at least - + filter operator==(part_of_speech value) const; // Part of speech equality filter operator==(positioning value) const; // Adjective positioning equality filter operator==(inflection value) const; // Inflection category equality - + filter operator==(bool value) const; // Boolean equality - + filter operator==(std::string value) const; // String equality filter operator!=(std::string value) const; // String inequality filter operator%=(std::string value) const; // String matching - + operator filter() const; // Non-nullity filter operator!() const; // Nullity - + filter operator%=(filter joinCondition) const; // Join - + private: - + // Constructor - + field( object obj, type datatype, @@ -281,26 +282,26 @@ namespace verbly { foreignJoinColumn_(foreignJoinColumn) { } - + // General object object_ = object::undefined; type type_ = type::undefined; const char* column_ = 0; const char* table_ = 0; - + // Non-joins and belongs-to joins bool nullable_ = false; - + // Joins object joinObject_ = object::undefined; - + // Many-to-many joins const char* foreignColumn_ = 0; const char* joinColumn_ = 0; const char* foreignJoinColumn_ = 0; - + }; - + }; #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 { { filter normalized = child.normalize(context); - // Notably, this does not attempt to merge hierarchal matches. + // Notably, this does not attempt to merge hierarchal matches, + // UNLESS they are positive matches being OR-d, or negative + // matches being ANDed. switch (normalized.getType()) { case type::singleton: @@ -1306,7 +1308,7 @@ namespace verbly { { if (!negativeJoins.count(normalized.singleton_.filterField)) { - negativeJoins[normalized.getField()] = filter(group_.orlogic); + negativeJoins[normalized.getField()] = filter(!group_.orlogic); } negativeJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join); @@ -1314,6 +1316,30 @@ namespace verbly { break; } + case comparison::hierarchally_matches: + { + if (group_.orlogic) + { + positiveJoins[normalized.getField()] |= std::move(*normalized.singleton_.join); + } else { + result += std::move(normalized); + } + + break; + } + + case comparison::does_not_hierarchally_match: + { + if (!group_.orlogic) + { + negativeJoins[normalized.getField()] |= std::move(*normalized.singleton_.join); + } else { + result += std::move(normalized); + } + + break; + } + case comparison::int_equals: case comparison::int_does_not_equal: case comparison::int_is_at_least: @@ -1327,8 +1353,6 @@ namespace verbly { case comparison::string_is_not_like: case comparison::is_null: case comparison::is_not_null: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: { result += std::move(normalized); -- cgit 1.4.1