* Add further optimizations: * Projection * When it contains a Rename, if the renamed attributes are projected away, then the rename can be removed. * Operation Order: * Projection containing an Order * Should remove the Order, since it is a noop * Projection should follow Rename * When a Projection contains a Restriction, wrap the Projection in the Restriction, projecting away any attributes not used in the restriction. If there are any remaining attributes, then wrap the operation in a Projection removing those attributes. * If all attributes are being used in the Restriction do nothing * When a Projection contains a Join, wrap the Join with a Projection of all the headers, minus those used in the Join. If there were any used, then wrap the whole operation in a Projection with the remaining attributes. * If all the attributes are used in the Join, do nothing * Try to use the same approach for Product * Test if it's possible to fully distribute projections over joins rather than splitting it up like this. * Restriction should follow Projection * Restriction optimizations: * "attr > ? OR attr > ?" -> "attr > ?", with the least restrictive value * Do the same for >=, <, <= * "attr > ? AND attr > ?" -> "attr > ?", with the most restrictive value * Do the same for >=, <, <= * "attr > 5 OR attr == 5" -> "attr >= 5" * "attr < 5 OR attr == 5" -> "attr <= 5" * "attr" = "string" AND "attr" =~ /string/ -> "attr" = "string" * If the regexp matches the constant, then it should be optimized down to a constant match. If it does not match then it should be optimized to a Contradiction. * Constant folding, eg: "attr1 > attr2 AND attr1 = 5" -> "5 > attr2 AND attr1 = 5" * This will probably only work across Conjunctions. * "attr > 5 AND attr = 6" -> "attr = 6", because attr must be equal to 6. this will probably be related to constant folding; the first expression will become 6 > 5, which evaluates to a Tautology, then the expression is a Tautology AND attr = 6, which simplifies down to attr = 6. * "attr < 5 AND attr = 6" -> "Contradiction", because attr must be equal to 6, and 6 < 5 evaluates to a Contradiction. A Contradiction AND attr = 6 simplifies down to a Contradiction. * Figure out how to reorganize the Restriction predicates so that all similar operations are closer together to allow more efficient optimizations. This would allow optimizations of stuff like this: "attr1 = ? OR attr2 = ? OR attr1 = ?" Into: "attr1 IN(..) OR attr2 = ?" * Rename should distribute over Join, Product and Set operations * The goal should be to push Rename as close to the base tables as possible so that the names of attribute will be consistent throughout the whole tree. * A Union of relations with the same base, header, and restrictions should try to combine into a single relation with the restrictions using OR. * An Intersection of relations with the same base, header, and restrictions should try to combine into a single relation with the restrictions using AND. * A Difference of relations with the same base and restrictions should try to combine into a single relation with the restrictions using NOT. * Join Optimizations * When a Join contains a Join, and the size of the base relations is known, join the smallest with the largest, and then join that result with the remaining relation. * Make sure the smallest relation (with a known size) is always the right-most operation. * When a restriction uses a unique index: * Order can be factored out * Limit with a limit >= 1 can be factored out * Offset with an offset > 0 can be transformed into an empty relation, since at most there can be only one match.