001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2011-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.server;
011
012import mondrian.olap.*;
013import mondrian.rolap.RolapSchema;
014import mondrian.spi.ProfileHandler;
015
016import java.sql.SQLException;
017import java.util.concurrent.atomic.AtomicLong;
018
019/**
020 * Implementation of {@link Statement}.
021 *
022 * <p>Not part of Mondrian's public API. This class may change without
023 * notice.</p>
024 *
025 * @author jhyde
026 */
027public abstract class StatementImpl implements Statement {
028    private static AtomicLong SEQ = new AtomicLong();
029
030    /**
031     * Writer to which to send profiling information, or null if profiling is
032     * disabled.
033     */
034    private ProfileHandler profileHandler;
035
036    protected Query query;
037
038    /**
039     * Query timeout, in milliseconds
040     */
041    protected long queryTimeout =
042        MondrianProperties.instance().QueryTimeout.get() * 1000;
043
044    /**
045     * The current execution context, or null if query is not executing.
046     */
047    private Execution execution;
048
049    /**
050     * Whether {@link #cancel()} was called before the statement was started.
051     * When the statement is started, it will immediately be marked canceled.
052     */
053    private boolean cancelBeforeStart;
054
055    private final long id;
056
057    /**
058     * Creates a StatementImpl.
059     */
060    public StatementImpl() {
061        this.id = SEQ.getAndIncrement();
062    }
063
064    public synchronized void start(Execution execution) {
065        if (this.execution != null) {
066            throw new AssertionError();
067        }
068        if (execution.statement != this) {
069            throw new AssertionError();
070        }
071        this.execution = execution;
072        execution.start();
073        if (cancelBeforeStart) {
074            execution.cancel();
075            cancelBeforeStart = false;
076        }
077    }
078
079    public synchronized void cancel() throws SQLException {
080        if (execution == null) {
081            // There is no current execution. Flag that we need to cancel as
082            // soon as we start execution.
083            cancelBeforeStart = true;
084        } else {
085            execution.cancel();
086        }
087    }
088
089    public synchronized void end(Execution execution) {
090        if (execution == null
091            || execution != this.execution)
092        {
093            throw new IllegalArgumentException(
094                execution + " != " + this.execution);
095        }
096        this.execution = null;
097        execution.end();
098    }
099
100    public void enableProfiling(ProfileHandler profileHandler) {
101        this.profileHandler = profileHandler;
102    }
103
104    public ProfileHandler getProfileHandler() {
105        return profileHandler;
106    }
107
108    public void setQueryTimeoutMillis(long timeoutMillis) {
109        this.queryTimeout = timeoutMillis;
110    }
111
112    public long getQueryTimeoutMillis() {
113        return queryTimeout;
114    }
115
116    public void checkCancelOrTimeout() {
117        final Execution execution0 = execution;
118        if (execution0 == null) {
119            return;
120        }
121        execution0.checkCancelOrTimeout();
122    }
123
124    public SchemaReader getSchemaReader() {
125        return getMondrianConnection().getSchemaReader().withLocus();
126    }
127
128    public RolapSchema getSchema() {
129        return getMondrianConnection().getSchema();
130    }
131
132    public Object getProperty(String name) {
133        return getMondrianConnection().getProperty(name);
134    }
135
136    public Query getQuery() {
137        return query;
138    }
139
140    public void setQuery(Query query) {
141        this.query = query;
142    }
143
144    public Execution getCurrentExecution() {
145        return execution;
146    }
147
148    public long getId() {
149        return id;
150    }
151}
152
153// End StatementImpl.java