new MergeProjections(),
new SimplifyExpressions(metadata, sqlParser), // Re-run the SimplifyExpressions to simplify any recomposed expressions from other optimizations
new UnaliasSymbolReferences(), // Run again because predicate pushdown might add more projections
new IndexJoinOptimizer(indexManager), // Run this after projections and filters have been fully simplified and pushed down
new CountConstantOptimizer(),
new WindowFilterPushDown(metadata), // This must run after PredicatePushDown so that it squashes any successive filter nodes
new PruneUnreferencedOutputs(), // Make sure to run this at the end to help clean the plan for logging/execution and not remove info that other optimizers might need at an earlier point
new PruneRedundantProjections()); // This MUST run after PruneUnreferencedOutputs as it may introduce new redundant projections
// TODO: consider adding a formal final plan sanitization optimizer that prepares the plan for transmission/execution/logging
// TODO: figure out how to improve the set flattening optimizer so that it can run at any point