docs: public VoltXMLDiff runDDLCommandAndDiff(HSQLDDLInfo stmtInfo,
                                              String ddl)
                                              throws HSQLParseException
      {
          // name of the table we're going to have to diff (if any)
          String expectedTableAffected = null;
  
          // If we fail to pre-process a statement, then we want to fail, but we're
          // still going to run the statement through HSQL to get its error message.
          // This variable helps us make sure we don't fail to preprocess and then
          // succeed at runnign the statement through HSQL.
          boolean expectFailure = false;
  
          // If cascade, we're going to need to look for any views that might have
          // gotten deleted. So get a list of all tables and views that existed before
          // we run the ddl, then we'll do a comparison later.
          Set<String> existingTableNames = null;
  
          if (stmtInfo != null) {
              if (stmtInfo.cascade) {
                  existingTableNames = getTableNames();
              }
  
              // we either have an index name or a table/view name, but not both
              if (stmtInfo.noun == HSQLDDLInfo.Noun.INDEX) {
                  if (stmtInfo.verb == HSQLDDLInfo.Verb.CREATE) {
                      expectedTableAffected = stmtInfo.secondName;
                  }
                  else {
                      expectedTableAffected = tableNameForIndexName(stmtInfo.name);
                  }
              }
              else {
                  expectedTableAffected = stmtInfo.name;
              }
  
              // Note that we're assuming ifexists can't happen with "create"
              expectFailure = (expectedTableAffected == null) && !stmtInfo.ifexists;
          }
          else {
              expectFailure = true;
          }
  
          runDDLCommand(ddl);
  
          // If we expect to fail, but the statement above didn't bail...
          // (Shouldn't get here ever I think)
          if (expectFailure) {
              throw new HSQLParseException("Unable to plan statement due to VoltDB DDL pre-processing error");
          }
          // sanity checks for non-failure
          assert(stmtInfo != null);
  
          // get old and new XML representations for the affected table
          VoltXMLElement tableXMLNew = null, tableXMLOld = null;
          if (expectedTableAffected != null) {
              tableXMLNew = getXMLForTable(expectedTableAffected);
              tableXMLOld = lastSchema.get(expectedTableAffected);
          }
  
          // valid reasons for tableXMLNew to be null are DROP IF EXISTS and not much else
          if (tableXMLNew == null) {
              tableXMLNew = emptySchema;
          }
  
          // the old table can be null for CREATE TABLE or for IF EXISTS stuff
          if (tableXMLOld == null) {
              tableXMLOld = emptySchema;
          }
  
          VoltXMLDiff diff = VoltXMLElement.computeDiff(tableXMLOld, tableXMLNew);
  
          // now find any views that might be missing and make sure the diff reflects that
          // they're gone
          if (stmtInfo.cascade) {
              Set<String> finalTableNames = getTableNames();
              for (String tableName : existingTableNames) {
                  if (!finalTableNames.contains(tableName)) {
                      tableName = tableName.toLowerCase();
                      tableXMLOld = lastSchema.get(tableName).children.get(0);
                      lastSchema.remove(tableName);
                      if (tableName.equals(expectedTableAffected)) {
                          continue;
                      }
                      diff.m_removedElements.add(tableXMLOld);
                  }
              }
          }
  
          // this is a hack to allow the diff-apply-er to accept a diff that has no order
          diff.m_elementOrder.clear();
  
          // remember the current schema
          if (expectedTableAffected != null) {
              lastSchema.put(expectedTableAffected, tableXMLNew.duplicate());
          }
          return diff;
      }