unsigned count = cond1->count();
for(unsigned i=0; i<count; ++i)
if(Condition *sub = dispatch_flatten(cond1->get(i).clone(), (i+1<count ? cond2->clone() : cond2)))
- result->add(sub);
+ add_merged_to(sub, result, true);
delete cond1;
if(result->is_viable())
for(unsigned i=0; i<count1; ++i)
for(unsigned j=0; j<count2; ++j)
if(Condition *sub = dispatch_flatten(cond1->get(i).clone(), cond2->get(j).clone()))
- result->add(sub);
+ add_merged_to(sub, result, true);
delete cond1;
delete cond2;
return 0;
}
+bool AndCondition::can_merge(const Condition &other, const CompoundCondition &parent) const
+{
+ const AndCondition *other_and = dynamic_cast<const AndCondition *>(&other);
+ if(!other_and || !dynamic_cast<const OrCondition *>(&parent))
+ return false;
+
+ return merge(*this, *other_and, parent, 0);
+}
+
+AndCondition *AndCondition::merge(const vector<const Condition *> &conds, const CompoundCondition &parent) const
+{
+ if(conds.size()!=2)
+ return 0;
+
+ const AndCondition *and1 = dynamic_cast<const AndCondition *>(conds[0]);
+ const AndCondition *and2 = dynamic_cast<const AndCondition *>(conds[1]);
+ if(!and1 || !and2 || !dynamic_cast<const OrCondition *>(&parent))
+ return 0;
+
+ AndCondition *result = 0;
+ merge(*and1, *and2, parent, &result);
+ return result;
+}
+
+bool AndCondition::merge(const AndCondition &cond1, const AndCondition &cond2, const CompoundCondition &parent, AndCondition **result)
+{
+ if(cond1.count()!=cond2.count())
+ return false;
+
+ int merge1 = -1;
+ vector<bool> used(cond1.count(), false);
+ for(unsigned i=0; i<cond1.count(); ++i)
+ {
+ int match = -1;
+ for(unsigned j=0; (match<0 && j<cond2.count()); ++j)
+ if(!used[j] && cond1.get(i).equals(cond2.get(j)))
+ match = j;
+
+ if(match>=0)
+ used[match] = true;
+ else if(merge1<0)
+ merge1 = i;
+ else
+ return false;
+ }
+
+ if(merge1>=0)
+ {
+ vector<const Condition *> merge_conds(2, 0);
+ merge_conds[0] = &cond1.get(merge1);
+ for(unsigned i=0; (!merge_conds[1] && i<cond2.count()); ++i)
+ if(!used[i])
+ merge_conds[1] = &cond2.get(i);
+
+ if(!merge_conds[1] || !merge_conds[0]->can_merge(*merge_conds[1], parent))
+ return false;
+
+ if(result)
+ {
+ *result = new AndCondition;
+ (*result)->add(merge_conds[0]->merge(merge_conds, parent));
+ }
+ }
+ else if(result)
+ *result = new AndCondition;
+
+ if(result)
+ {
+ for(unsigned i=0; i<cond2.count(); ++i)
+ if(used[i])
+ (*result)->add(cond2.get(i).clone());
+ }
+
+ return true;
+}
+
bool AndCondition::is_viable() const
{
for(vector<Condition *>::const_iterator i=conditions.begin(); i!=conditions.end(); ++i)
virtual Condition *flatten(OrCondition *, Condition *) const;
virtual Condition *flatten(OrCondition *, AndCondition *) const;
virtual Condition *flatten(OrCondition *, OrCondition *) const;
+public:
+ virtual bool can_merge(const Condition &, const CompoundCondition &) const;
+ virtual AndCondition *merge(const std::vector<const Condition *> &, const CompoundCondition &) const;
+private:
+ static bool merge(const AndCondition &, const AndCondition &, const CompoundCondition &, AndCondition **);
public:
virtual bool is_viable() const;
virtual void add_lines(std::list<FilterStatement> &) const;