docs: VoltXMLElement voltGetXML(SimpleColumnContext context, String realAlias)
          throws HSQLParseException {
          // The voltXML representations of expressions tends to be driven much more by the expression's opType
          // than its Expression class.
          int exprOp = getType();
  
          // The opType value of "SIMPLE_COLUMN" is a special case that spans Expression classes and seems to
          // need to use the Expression's exact class to be able to correctly determine its VoltXMLElement
          // representation.
          // Last minute "SIMPLE_COLUMN" substitutions can blast a new opType into an Expression of a class
          // other than ExpressionColumn as an optimization for duplicated expressions.
          // VoltDB currently uses "alias" matching to navigate to the correct (duplicate) expression structure
          // typically an ExpressionAggregate.
          // The prototypes dictionary is set up to handle a SIMPLE_COLUMN of any class EXCEPT ExpressionColumn.
          // A SIMPLE_COLUMN ExpressionColumn can be treated as a normal "COLUMN" ExpressionColumn.
          // That case gets explicitly enabled here by fudging the opType from SIMPLE_COLUMN to COLUMN.
          if (exprOp == OpTypes.SIMPLE_COLUMN) {
              VoltXMLElement asResolved = context.resolveSimpleColumn(this);
              if (asResolved != null) {
                  return asResolved;
              }
              // ENG-10429 moved the following two lines here. See fix note https://issues.voltdb.com/browse/ENG-10429.
              // convert the SIMPLE_COLUMN into a COLUMN
              opType = OpTypes.COLUMN;
              exprOp = OpTypes.COLUMN;
          }
  
          // Use the opType to find a pre-initialized prototype VoltXMLElement with the correct
          // name and any required hard-coded values pre-set.
          VoltXMLElement exp = prototypes.get(exprOp);
          if (exp == null) {
              // Must have found an unsupported opType.
              throwForUnsupportedExpression(exprOp);
          }
  
          // Duplicate the prototype and add any expression particulars needed for the specific opType value,
          // as well as a unique identifier, a possible alias, and child nodes.
          exp = exp.duplicate();
          exp.attributes.put("id", getUniqueId(context.m_session));
  
          if (realAlias != null) {
              exp.attributes.put("alias", realAlias);
          }
          else if ((alias != null) && (getAlias().length() > 0)) {
              exp.attributes.put("alias", getAlias());
          }
  
          // Add expression sub type
          if (exprSubType == OpTypes.ANY_QUANTIFIED) {
              exp.attributes.put("opsubtype", "any");
          }
          else if (exprSubType == OpTypes.ALL_QUANTIFIED) {
              exp.attributes.put("opsubtype", "all");
          }
  
          for (Expression expr : nodes) {
              if (expr != null) {
                  VoltXMLElement vxmle = expr.voltGetXML(context, null);
                  exp.children.add(vxmle);
                  assert(vxmle != null);
              }
          }
  
          // Few opTypes need additional special case detailing or special case error detection.
          // Very few need access to members defined on specific Expression classes, but they
          // can usually be accessed via down-casting.
          // Even fewer need private members, and they are accessed by delegation to a
          // class-specific voltAnnotate... member function that directly manipulates the
          // VoltXMLElement.
          switch (exprOp) {
          case OpTypes.VALUE:
              // Apparently at this stage, all valid non-NULL values must have a
              // type determined by HSQL.
              // (I'm not sure why this MUST be the case --paul.)
              if (valueData == null) {
                  String valueType = (dataType == null) ? "NULL" :
                          Types.getTypeName(dataType.typeCode);
                  exp.attributes.put("valuetype", valueType);
                  return exp;
              }
  
              exp.attributes.put("valuetype", Types.getTypeName(dataType.typeCode));
  
              if (valueData instanceof TimestampData) {
                  // When we get the default from the DDL,
                  // it gets jammed into a TimestampData object.  If we
                  // don't do this, we get a Java class/reference
                  // string in the output schema for the DDL.
                  // EL HACKO: I'm just adding in the timezone seconds
                  // at the moment, hope this is right --izzy
                  TimestampData time = (TimestampData) valueData;
                  exp.attributes.put("value", Long.toString(Math.round((time.getSeconds() +
                                                                        time.getZone()) * 1e6) +
                                                            time.getNanos() / 1000));
                  return exp;
              }
  
              // convert binary values to hex
              if (valueData instanceof BinaryData) {
                  BinaryData bd = (BinaryData) valueData;
                  exp.attributes.put("value", hexEncode(bd.getBytes()));
                  return exp;
              }
  
              // Otherwise just string format the value.
              if (dataType instanceof NumberType && ! dataType.isIntegralType()) {
                  // remove the scentific exponent notation
                  exp.attributes.put("value", new BigDecimal(valueData.toString()).toPlainString());
                  return exp;
              }
              exp.attributes.put("value", valueData.toString());
              return exp;
  
          case OpTypes.COLUMN:
              ExpressionColumn ec = (ExpressionColumn)this;
              return ec.voltAnnotateColumnXML(exp);
  
          case OpTypes.COALESCE:
              return convertUsingColumnrefToCoaleseExpression(context.m_session, exp, dataType);
  
          case OpTypes.SQL_FUNCTION:
              FunctionSQL fn = (FunctionSQL)this;
              return fn.voltAnnotateFunctionXML(exp);
  
          case OpTypes.COUNT:
          case OpTypes.SUM:
          case OpTypes.AVG:
              if (((ExpressionAggregate)this).isDistinctAggregate) {
                  exp.attributes.put("distinct", "true");
              }
              return exp;
  
          case OpTypes.ORDER_BY:
              if (((ExpressionOrderBy)this).isDescending()) {
                  exp.attributes.put("desc", "true");
              }
              return exp;
  
          case OpTypes.CAST:
              if (dataType == null) {
                  throw new HSQLParseException(
                          "VoltDB could not determine the type in a CAST operation");
              }
              exp.attributes.put("valuetype", dataType.getNameString());
              return exp;
  
          case OpTypes.TABLE_SUBQUERY:
              if (subQuery == null || subQuery.queryExpression == null) {
                  throw new HSQLParseException("VoltDB could not determine the subquery");
              }
              ExpressionColumn parameters[] = new ExpressionColumn[0];
              exp.children.add(StatementQuery.voltGetXMLExpression(subQuery.queryExpression,
                      parameters, context.m_session));
              return exp;
  
          case OpTypes.ALTERNATIVE:
              assert(nodes.length == 2);
              // If with ELSE clause, pad NULL with it.
              if (nodes[RIGHT] instanceof ExpressionValue) {
                  ExpressionValue val = (ExpressionValue) nodes[RIGHT];
                  if (val.valueData == null && val.dataType == Type.SQL_ALL_TYPES) {
                      exp.children.get(RIGHT).attributes.put("valuetype", dataType.getNameString());
                  }
              }
          case OpTypes.CASEWHEN:
              // Hsql has check dataType can not be null.
              assert(dataType != null);
              exp.attributes.put("valuetype", dataType.getNameString());
              return exp;
  
          case OpTypes.WINDOWED_RANK:
          case OpTypes.WINDOWED_DENSE_RANK:
          case OpTypes.WINDOWED_ROW_NUMBER:
          case OpTypes.WINDOWED_COUNT:
          case OpTypes.WINDOWED_MIN:
          case OpTypes.WINDOWED_MAX:
          case OpTypes.WINDOWED_SUM:
              assert(dataType != null);
              assert(this instanceof ExpressionWindowed);
              exp.attributes.put("valuetype", dataType.getNameString());
              ExpressionWindowed erank = (ExpressionWindowed) this;
              return erank.voltAnnotateWindowedAggregateXML(exp, context);
  
          default:
              return exp;
          }
      }