@Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    if (!super.equals(o)) {
      return false;
    }

    GroupByQuery that = (GroupByQuery) o;

    if (aggregatorSpecs != null
        ? !aggregatorSpecs.equals(that.aggregatorSpecs)
        : that.aggregatorSpecs != null) {
      return false;
    }
    if (dimFilter != null ? !dimFilter.equals(that.dimFilter) : that.dimFilter != null) {
      return false;
    }
    if (dimensions != null ? !dimensions.equals(that.dimensions) : that.dimensions != null) {
      return false;
    }
    if (granularity != null ? !granularity.equals(that.granularity) : that.granularity != null) {
      return false;
    }
    if (havingSpec != null ? !havingSpec.equals(that.havingSpec) : that.havingSpec != null) {
      return false;
    }
    if (limitSpec != null ? !limitSpec.equals(that.limitSpec) : that.limitSpec != null) {
      return false;
    }
    if (limitFn != null ? !limitFn.equals(that.limitFn) : that.limitFn != null) {
      return false;
    }
    if (postAggregatorSpecs != null
        ? !postAggregatorSpecs.equals(that.postAggregatorSpecs)
        : that.postAggregatorSpecs != null) {
      return false;
    }

    return true;
  }
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    if (!super.equals(o)) {
      return false;
    }

    TimeBoundaryQuery that = (TimeBoundaryQuery) o;

    if (!bound.equals(that.bound)) {
      return false;
    }

    if (dimFilter != null ? !dimFilter.equals(that.dimFilter) : that.dimFilter != null) {
      return false;
    }

    return true;
  }