@Override
  public String rewriteFilterItem(FilterItem item) {
    if (item.isCompoundFilter()) {
      FilterItem[] childItems = item.getChildItems();
      StringBuilder sb = new StringBuilder();
      sb.append('(');
      for (int i = 0; i < childItems.length; i++) {
        FilterItem child = childItems[i];
        if (i != 0) {
          sb.append(' ');
          sb.append(item.getLogicalOperator().toString());
          sb.append(' ');
        }
        sb.append(rewriteFilterItem(child));
      }
      sb.append(')');
      return sb.toString();
    }

    final String primaryFilterSql = item.toSql(isSchemaIncludedInColumnPaths());

    final OperatorType operator = item.getOperator();
    if (operator == OperatorType.DIFFERENT_FROM) {
      final Object operand = item.getOperand();
      if (operand != null) {
        // special case in SQL where NULL is not treated as a value -
        // see Ticket #1058

        FilterItem isNullFilter =
            new FilterItem(item.getSelectItem(), OperatorType.EQUALS_TO, null);
        final String secondaryFilterSql = rewriteFilterItem(isNullFilter);

        return '(' + primaryFilterSql + " OR " + secondaryFilterSql + ')';
      }
    }

    return primaryFilterSql;
  }
  protected static void rewriteFilterItem(StringBuilder sb, FilterItem filterItem)
      throws UnsupportedOperationException {
    if (filterItem.isCompoundFilter()) {
      FilterItem[] childrend = filterItem.getChildItems();
      boolean firstChild = true;
      sb.append('(');
      for (FilterItem child : childrend) {
        if (firstChild) {
          firstChild = false;
        } else {
          sb.append(' ');
          sb.append(filterItem.getLogicalOperator().toString());
          sb.append(' ');
        }
        rewriteFilterItem(sb, child);
      }
      sb.append(')');
      return;
    }

    final SelectItem selectItem = filterItem.getSelectItem();
    validateSoqlSupportedSelectItem(selectItem);

    final Column column = selectItem.getColumn();
    sb.append(column.getName());
    sb.append(' ');

    final OperatorType operator = filterItem.getOperator();
    if (OperatorType.IN.equals(operator)) {
      throw new UnsupportedOperationException("IN operator not supported: " + filterItem);
    }
    sb.append(operator.toSql());
    sb.append(' ');

    final Object operand = filterItem.getOperand();
    if (operand == null) {
      sb.append("null");
    } else if (operand instanceof String) {
      sb.append('\'');

      String str = operand.toString();
      str = str.replaceAll("\'", "\\\\'");
      str = str.replaceAll("\"", "\\\\\"");
      str = str.replaceAll("\r", "\\\\r");
      str = str.replaceAll("\n", "\\\\n");
      str = str.replaceAll("\t", "\\\\t");

      sb.append(str);
      sb.append('\'');
    } else if (operand instanceof Number) {
      sb.append(operand);
    } else if (operand instanceof Date) {
      final SimpleDateFormat dateFormat;
      ColumnType expectedColumnType = selectItem.getExpectedColumnType();
      if (expectedColumnType == ColumnType.DATE) {
        // note: we don't apply the timezone for DATE fields, since they
        // don't contain time-of-day information.
        dateFormat = new SimpleDateFormat(SOQL_DATE_FORMAT_OUT);
      } else if (expectedColumnType == ColumnType.TIME) {
        dateFormat = new SimpleDateFormat(SOQL_TIME_FORMAT_OUT, Locale.ENGLISH);
        dateFormat.setTimeZone(SOQL_TIMEZONE);
      } else {
        dateFormat = new SimpleDateFormat(SOQL_DATE_TIME_FORMAT_OUT, Locale.ENGLISH);
        dateFormat.setTimeZone(SOQL_TIMEZONE);
      }

      String str = dateFormat.format((Date) operand);
      logger.debug("Date '{}' formatted as: {}", operand, str);
      sb.append(str);
    } else if (operand instanceof Column) {
      sb.append(((Column) operand).getName());
    } else if (operand instanceof SelectItem) {
      SelectItem operandSelectItem = (SelectItem) operand;
      validateSoqlSupportedSelectItem(operandSelectItem);
      sb.append(operandSelectItem.getColumn().getName());
    } else {
      throw new UnsupportedOperationException("Unsupported operand: " + operand);
    }
  }