docs: private void setupForNewPlans(AbstractParsedStmt parsedStmt) {
          m_bestAndOnlyPlanWasGenerated = false;
          m_partitioning.analyzeTablePartitioning(parsedStmt.allScans());
  
          if (parsedStmt instanceof ParsedUnionStmt) {
              m_parsedUnion = (ParsedUnionStmt) parsedStmt;
              return;
          }
  
          if (parsedStmt instanceof ParsedSelectStmt) {
              if (tableListIncludesExportOnly(parsedStmt.m_tableList)) {
                  throw new PlanningErrorException(
                          "Illegal to read a stream.");
              }
  
              m_parsedSelect = (ParsedSelectStmt) parsedStmt;
              // Simplify the outer join if possible
              if (m_parsedSelect.m_joinTree instanceof BranchNode) {
                  if (! m_parsedSelect.hasJoinOrder()) {
                      simplifyOuterJoin((BranchNode)m_parsedSelect.m_joinTree);
                  }
  
                  // Convert RIGHT joins to the LEFT ones
                  ((BranchNode)m_parsedSelect.m_joinTree).toLeftJoin();
              }
              m_subAssembler = new SelectSubPlanAssembler(m_catalogDb, m_parsedSelect, m_partitioning);
  
              // Process the GROUP BY information, decide whether it is group by the partition column
              if (isPartitionColumnInGroupbyList(m_parsedSelect.groupByColumns())) {
                  m_parsedSelect.setHasPartitionColumnInGroupby();
              }
              if (isPartitionColumnInWindowedAggregatePartitionByList()) {
                  m_parsedSelect.setHasPartitionColumnInWindowedAggregate();
              }
  
              // FIXME: is the following scheme/comment obsolete?
              // FIXME: turn it on when we are able to push down DISTINCT
  //            if (isPartitionColumnInGroupbyList(m_parsedSelect.m_distinctGroupByColumns)) {
  //                m_parsedSelect.setHasPartitionColumnInDistinctGroupby();
  //            }
  
              return;
          }
  
          // @TODO
          // Need to use StmtTableScan instead
          // check that no modification happens to views
          if (tableListIncludesReadOnlyView(parsedStmt.m_tableList)) {
              throw new PlanningErrorException("Illegal to modify a materialized view.");
          }
  
          m_partitioning.setIsDML();
  
          // Don't parse a stream and a table.  Note that
          // for swap statements we return here.
          if (parsedStmt instanceof ParsedSwapStmt) {
              assert (parsedStmt.m_tableList.size() == 2);
              if (tableListIncludesExportOnly(parsedStmt.m_tableList)) {
                  throw new PlanningErrorException("Illegal to swap a stream.");
              }
              m_parsedSwap = (ParsedSwapStmt) parsedStmt;
              return;
          }
  
          // Check that only multi-partition writes are made to replicated tables.
          // figure out which table we're updating/deleting
          Table targetTable = parsedStmt.m_tableList.get(0);
          if (targetTable.getIsreplicated()) {
              if (m_partitioning.wasSpecifiedAsSingle()
                      && !m_partitioning.isReplicatedDmlToRunOnAllPartitions()) {
                  String msg = "Trying to write to replicated table '" + targetTable.getTypeName()
                          + "' in a single-partition procedure.";
                  throw new PlanningErrorException(msg);
              }
          }
          else if (m_partitioning.wasSpecifiedAsSingle() == false) {
              m_partitioning.setPartitioningColumnForDML(targetTable.getPartitioncolumn());
          }
  
          if (parsedStmt instanceof ParsedInsertStmt) {
              m_parsedInsert = (ParsedInsertStmt) parsedStmt;
              // The currently handled inserts are too simple to even require a subplan assembler. So, done.
              return;
          } else if (parsedStmt instanceof ParsedUpdateStmt) {
              if (tableListIncludesExportOnly(parsedStmt.m_tableList)) {
                  throw new PlanningErrorException("Illegal to update a stream.");
              }
              m_parsedUpdate = (ParsedUpdateStmt) parsedStmt;
          } else if (parsedStmt instanceof ParsedDeleteStmt) {
              if (tableListIncludesExportOnly(parsedStmt.m_tableList)) {
                  throw new PlanningErrorException("Illegal to delete from a stream.");
              }
              m_parsedDelete = (ParsedDeleteStmt) parsedStmt;
          } else if (parsedStmt instanceof ParsedMigrateStmt) {
              m_parsedMigrate = (ParsedMigrateStmt) parsedStmt;
          } else {
              throw new RuntimeException("Unknown subclass of AbstractParsedStmt.");
          }
  
          if ( ! m_partitioning.wasSpecifiedAsSingle()) {
              //TODO: When updates and deletes can contain joins, this step may have to be
              // deferred so that the valueEquivalence set can be analyzed per join order.
              // This appears to be an unfortunate side effect of how the HSQL interface
              // misleadingly organizes the placement of join/where filters on the statement tree.
              // This throws off the accounting of equivalence join filters until they can be
              // normalized in analyzeJoinFilters, but that normalization process happens on a
              // per-join-order basis, and so, so must this analysis.
              HashMap<AbstractExpression, Set<AbstractExpression>>
                  valueEquivalence = parsedStmt.analyzeValueEquivalence();
              Collection<StmtTableScan> scans = parsedStmt.allScans();
              m_partitioning.analyzeForMultiPartitionAccess(scans, valueEquivalence);
          }
          m_subAssembler = new WriterSubPlanAssembler(m_catalogDb, parsedStmt, m_partitioning);
      }