org.apache.druid.query.BaseQuery.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.druid.query.BaseQuery.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.druid.query;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import org.apache.druid.guice.annotations.ExtensionPoint;
import org.apache.druid.java.util.common.granularity.Granularities;
import org.apache.druid.java.util.common.granularity.Granularity;
import org.apache.druid.java.util.common.granularity.PeriodGranularity;
import org.apache.druid.query.spec.QuerySegmentSpec;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
import org.joda.time.Interval;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 */
@ExtensionPoint
public abstract class BaseQuery<T extends Comparable<T>> implements Query<T> {
    public static void checkInterrupted() {
        if (Thread.interrupted()) {
            throw new QueryInterruptedException(new InterruptedException());
        }
    }

    public static final String QUERYID = "queryId";
    private final DataSource dataSource;
    private final boolean descending;
    private final Map<String, Object> context;
    private final QuerySegmentSpec querySegmentSpec;
    private volatile Duration duration;
    private final Granularity granularity;

    public BaseQuery(DataSource dataSource, QuerySegmentSpec querySegmentSpec, boolean descending,
            Map<String, Object> context) {
        this(dataSource, querySegmentSpec, descending, context, Granularities.ALL);
    }

    public BaseQuery(DataSource dataSource, QuerySegmentSpec querySegmentSpec, boolean descending,
            Map<String, Object> context, Granularity granularity) {
        Preconditions.checkNotNull(dataSource, "dataSource can't be null");
        Preconditions.checkNotNull(querySegmentSpec, "querySegmentSpec can't be null");
        Preconditions.checkNotNull(granularity, "Must specify a granularity");

        this.dataSource = dataSource;
        this.context = context;
        this.querySegmentSpec = querySegmentSpec;
        this.descending = descending;
        this.granularity = granularity;
    }

    @JsonProperty
    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @JsonProperty
    @Override
    public boolean isDescending() {
        return descending;
    }

    @JsonProperty("intervals")
    public QuerySegmentSpec getQuerySegmentSpec() {
        return querySegmentSpec;
    }

    @Override
    public QueryRunner<T> getRunner(QuerySegmentWalker walker) {
        return getQuerySegmentSpecForLookUp(this).lookup(this, walker);
    }

    @VisibleForTesting
    public static QuerySegmentSpec getQuerySegmentSpecForLookUp(BaseQuery query) {
        if (query.getDataSource() instanceof QueryDataSource) {
            QueryDataSource ds = (QueryDataSource) query.getDataSource();
            Query subquery = ds.getQuery();
            if (subquery instanceof BaseQuery) {
                return getQuerySegmentSpecForLookUp((BaseQuery) subquery);
            }
            throw new IllegalStateException("Invalid subquery type " + subquery.getClass());
        }
        return query.getQuerySegmentSpec();
    }

    @Override
    public List<Interval> getIntervals() {
        return querySegmentSpec.getIntervals();
    }

    @Override
    public Duration getDuration() {
        if (duration == null) {
            Duration totalDuration = new Duration(0);
            for (Interval interval : querySegmentSpec.getIntervals()) {
                if (interval != null) {
                    totalDuration = totalDuration.plus(interval.toDuration());
                }
            }
            duration = totalDuration;
        }

        return duration;
    }

    @Override
    @JsonProperty
    public Granularity getGranularity() {
        return granularity;
    }

    @Override
    public DateTimeZone getTimezone() {
        return granularity instanceof PeriodGranularity ? ((PeriodGranularity) granularity).getTimeZone()
                : DateTimeZone.UTC;
    }

    @Override
    @JsonProperty
    public Map<String, Object> getContext() {
        return context;
    }

    @Override
    public <ContextType> ContextType getContextValue(String key) {
        return context == null ? null : (ContextType) context.get(key);
    }

    @Override
    public <ContextType> ContextType getContextValue(String key, ContextType defaultValue) {
        ContextType retVal = getContextValue(key);
        return retVal == null ? defaultValue : retVal;
    }

    @Override
    public boolean getContextBoolean(String key, boolean defaultValue) {
        return QueryContexts.parseBoolean(this, key, defaultValue);
    }

    /**
     * @deprecated use {@link #computeOverriddenContext(Map, Map) computeOverriddenContext(getContext(), overrides))}
     * instead. This method may be removed in the next minor or major version of Druid.
     */
    @Deprecated
    protected Map<String, Object> computeOverridenContext(final Map<String, Object> overrides) {
        return computeOverriddenContext(getContext(), overrides);
    }

    protected static Map<String, Object> computeOverriddenContext(final Map<String, Object> context,
            final Map<String, Object> overrides) {
        Map<String, Object> overridden = Maps.newTreeMap();
        if (context != null) {
            overridden.putAll(context);
        }
        overridden.putAll(overrides);

        return overridden;
    }

    @Override
    public Ordering<T> getResultOrdering() {
        Ordering<T> retVal = Ordering.natural();
        return descending ? retVal.reverse() : retVal;
    }

    @Override
    public String getId() {
        return (String) getContextValue(QUERYID);
    }

    @Override
    public Query withId(String id) {
        return withOverriddenContext(ImmutableMap.of(QUERYID, id));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        BaseQuery<?> baseQuery = (BaseQuery<?>) o;
        return descending == baseQuery.descending && Objects.equals(dataSource, baseQuery.dataSource)
                && Objects.equals(context, baseQuery.context)
                && Objects.equals(querySegmentSpec, baseQuery.querySegmentSpec)
                && Objects.equals(duration, baseQuery.duration)
                && Objects.equals(granularity, baseQuery.granularity);
    }

    @Override
    public int hashCode() {

        return Objects.hash(dataSource, descending, context, querySegmentSpec, duration, granularity);
    }
}