/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server.types;
import com.foundationdb.qp.operator.QueryContext;
import com.foundationdb.qp.operator.QueryContext.NotificationLevel;
import com.foundationdb.server.error.ErrorCode;
import com.foundationdb.server.error.InvalidOperationException;
import com.foundationdb.server.error.InvalidParameterValueException;
import com.foundationdb.server.error.OverflowException;
import com.foundationdb.server.error.StringTruncationException;
import com.foundationdb.util.SparseArray;
import com.google.common.base.Objects;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Locale;
public final class TExecutionContext {
public Object objectAt(int index) {
Object result = null;
if (preptimeCache != null && preptimeCache.isDefined(index))
result = preptimeCache.get(index);
if (result == null && exectimeCache != null && exectimeCache.isDefined(index))
result = exectimeCache.get(index);
return result;
}
public TInstance outputType() {
return outputType;
}
public Object preptimeObjectAt(int index) {
if ((preptimeCache != null) && preptimeCache.isDefined(index))
return preptimeCache.get(index);
else
return null;
}
public boolean hasExectimeObject(int index) {
return exectimeCache != null && exectimeCache.isDefined(index);
}
public Object exectimeObjectAt(int index) {
if (exectimeCache == null)
exectimeCache = new SparseArray<>();
return exectimeCache.get(index);
}
public void putExectimeObject(int index, Object value) {
if (preptimeCache != null && preptimeCache.isDefined(index)) {
Object conflict = preptimeCache.get(index);
if (conflict != null)
throw new IllegalStateException("conflicts with preptime value: " + conflict);
}
if (exectimeCache == null)
exectimeCache = new SparseArray<>(index);
exectimeCache.set(index, value);
}
public void notifyClient(NotificationLevel level, ErrorCode errorCode, String message) {
if (queryContext == null)
logger.warn("no query context on which to report error {}: {}", errorCode, message);
else
queryContext.notifyClient(level, errorCode, message);
}
public QueryContext getQueryContext()
{
return queryContext;
}
public void warnClient(InvalidOperationException exception) {
if (queryContext == null)
logger.warn("no query context on which to report exception", exception);
else
queryContext.warnClient(exception);
}
public void logError (String msg)
{
logger.error(msg);
}
public Locale getCurrentLocale()
{
// TODO: need to get this from the session
return Locale.getDefault();
}
/**
* Some functions need to get the current timezone (session/global), not the JVM's timezone.
* @return the server's timezone.
*/
public String getCurrentTimezone()
{
// TODO need to get this from the session
return DateTimeZone.getDefault().getID();
}
/**
*
* @return the time at which the query started
*/
public long getCurrentDate()
{
return queryContext.getStartTime();
}
public String getCurrentUser()
{
return queryContext.getCurrentUser();
}
public String getSessionUser()
{
return queryContext.getSessionUser();
}
public String getSystemUser()
{
return queryContext.getSystemUser();
}
public String getCurrentSchema()
{
return queryContext.getCurrentSchema();
}
public String getCurrentSetting(String key)
{
return queryContext.getCurrentSetting(key);
}
public int getSessionId()
{
return queryContext.getSessionId();
}
public void reportOverflow(String msg)
{
switch(overflowHandling)
{
case WARN:
warnClient(new OverflowException());
break;
case ERROR:
throw new OverflowException();
case IGNORE:
// ignores, does nothing
break;
default:
throw new AssertionError(overflowHandling);
}
}
public void reportTruncate(String original, String truncated)
{
switch(truncateHandling)
{
case WARN:
warnClient(new StringTruncationException(original, truncated));
break;
case ERROR:
throw new StringTruncationException(original, truncated);
case IGNORE:
// ignores, does nothing
break;
default:
throw new AssertionError(truncateHandling);
}
}
public void reportBadValue(String msg)
{
switch(invalidFormatHandling)
{
case WARN:
warnClient(new InvalidParameterValueException(msg));
break;
case ERROR:
throw new InvalidParameterValueException(msg);
case IGNORE:
// ignores, does nothing
break;
default:
throw new AssertionError(invalidFormatHandling);
}
}
public void setQueryContext(QueryContext queryContext) {
this.queryContext = queryContext;
}
public TExecutionContext deriveContext(List<TInstance> inputTypes, TInstance outputType) {
return new TExecutionContext(
new SparseArray<>(),
inputTypes,
outputType,
queryContext,
overflowHandling,
truncateHandling,
invalidFormatHandling
);
}
// state
public TExecutionContext(List<TInstance> inputTypes, TInstance outputType, QueryContext queryContext) {
this(null, inputTypes, outputType, queryContext, null, null, null);
}
public TExecutionContext(SparseArray<Object> preptimeCache,
List<TInstance> inputTypes,
TInstance outputType,
QueryContext queryContext,
ErrorHandlingMode overflow,
ErrorHandlingMode truncate,
ErrorHandlingMode invalid)
{
this.preptimeCache = preptimeCache;
this.inputTypes = inputTypes;
this.outputType = outputType;
this.queryContext = queryContext;
overflowHandling = Objects.firstNonNull(overflow, ErrorHandlingMode.WARN);
truncateHandling = Objects.firstNonNull(truncate, ErrorHandlingMode.WARN);
invalidFormatHandling = Objects.firstNonNull(invalid, ErrorHandlingMode.WARN);
}
private SparseArray<Object> preptimeCache;
private SparseArray<Object> exectimeCache;
private List<TInstance> inputTypes;
private TInstance outputType;
private QueryContext queryContext;
private ErrorHandlingMode overflowHandling;
private ErrorHandlingMode truncateHandling;
private ErrorHandlingMode invalidFormatHandling;
private static final Logger logger = LoggerFactory.getLogger(TExecutionContext.class);
}