blob: 8350a81e29f62dd5b3050296b4e59dd4c1b66ec4 [file] [log] [blame]
/*
* 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.ignite.internal.managers.systemview;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.query.h2.sys.view.SqlAbstractLocalSystemView;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.spi.systemview.view.SystemView;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeVisitor;
import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker.AttributeWithValueVisitor;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.table.Column;
import org.h2.value.Value;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueByte;
import org.h2.value.ValueDecimal;
import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
import org.h2.value.ValueString;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.internal.processors.metric.impl.MetricUtils.toSqlName;
/**
* SQL system view to export {@link SystemView} data.
*/
public class SystemViewLocal<R> extends SqlAbstractLocalSystemView {
/** */
private static final Map<Class<?>, Function<Object, ? extends Value>> CLS_TO_VAL = new HashMap<>();
/** */
private static final Function<Object, ? extends Value> DFLT_FUNC = val -> ValueString.get(Objects.toString(val));
/** */
private static final Map<Class<?>, Integer> CLS_TO_VAL_TYPE = new HashMap<>();
static {
CLS_TO_VAL_TYPE.put(String.class, Value.STRING);
CLS_TO_VAL_TYPE.put(IgniteUuid.class, Value.STRING);
CLS_TO_VAL_TYPE.put(UUID.class, Value.UUID);
CLS_TO_VAL_TYPE.put(Class.class, Value.STRING);
CLS_TO_VAL_TYPE.put(InetSocketAddress.class, Value.STRING);
CLS_TO_VAL_TYPE.put(BigDecimal.class, Value.DECIMAL);
CLS_TO_VAL_TYPE.put(BigInteger.class, Value.DECIMAL);
CLS_TO_VAL_TYPE.put(Date.class, Value.TIMESTAMP);
CLS_TO_VAL_TYPE.put(boolean.class, Value.BOOLEAN);
CLS_TO_VAL_TYPE.put(Boolean.class, Value.BOOLEAN);
CLS_TO_VAL_TYPE.put(byte.class, Value.BYTE);
CLS_TO_VAL_TYPE.put(Byte.class, Value.BYTE);
CLS_TO_VAL_TYPE.put(short.class, Value.SHORT);
CLS_TO_VAL_TYPE.put(Short.class, Value.SHORT);
CLS_TO_VAL_TYPE.put(int.class, Value.INT);
CLS_TO_VAL_TYPE.put(Integer.class, Value.INT);
CLS_TO_VAL_TYPE.put(long.class, Value.LONG);
CLS_TO_VAL_TYPE.put(Long.class, Value.LONG);
CLS_TO_VAL_TYPE.put(char.class, Value.STRING);
CLS_TO_VAL_TYPE.put(Character.class, Value.STRING);
CLS_TO_VAL_TYPE.put(float.class, Value.FLOAT);
CLS_TO_VAL_TYPE.put(Float.class, Value.FLOAT);
CLS_TO_VAL_TYPE.put(double.class, Value.DOUBLE);
CLS_TO_VAL_TYPE.put(Double.class, Value.DOUBLE);
CLS_TO_VAL.put(String.class, val -> ValueString.get(Objects.toString(val)));
CLS_TO_VAL.put(IgniteUuid.class, val -> ValueString.get(Objects.toString(val)));
CLS_TO_VAL.put(UUID.class, val -> ValueUuid.get((UUID)val));
CLS_TO_VAL.put(Class.class, val -> ValueString.get(((Class<?>)val).getName()));
CLS_TO_VAL.put(InetSocketAddress.class, val -> ValueString.get(Objects.toString(val)));
CLS_TO_VAL.put(BigDecimal.class, val -> ValueDecimal.get((BigDecimal)val));
CLS_TO_VAL.put(BigInteger.class, val -> ValueDecimal.get(new BigDecimal((BigInteger)val)));
CLS_TO_VAL.put(Date.class, val -> ValueTimestamp.fromMillis(((Date)val).getTime()));
CLS_TO_VAL.put(Boolean.class, val -> ValueBoolean.get((Boolean)val));
CLS_TO_VAL.put(Byte.class, val -> ValueByte.get((Byte)val));
CLS_TO_VAL.put(Short.class, val -> ValueShort.get((Short)val));
CLS_TO_VAL.put(Integer.class, val -> ValueInt.get((Integer)val));
CLS_TO_VAL.put(Long.class, val -> ValueLong.get((Long)val));
CLS_TO_VAL.put(Character.class, val -> ValueString.get(Objects.toString(val)));
CLS_TO_VAL.put(Float.class, val -> ValueFloat.get((Float)val));
CLS_TO_VAL.put(Double.class, val -> ValueDouble.get((Double)val));
}
/** System view for export. */
protected final SystemView<R> sysView;
/**
* @param ctx Kernal context.
* @param sysView View to export.
* @param indexes Indexed fields.
*/
protected SystemViewLocal(GridKernalContext ctx, SystemView<R> sysView, String[] indexes) {
super(toSqlName(sysView.name()), sysView.description(), ctx, indexes, columnsList(sysView));
this.sysView = sysView;
}
/**
* @param ctx Kernal context.
* @param sysView View to export.
*/
public SystemViewLocal(GridKernalContext ctx, SystemView<R> sysView) {
this(ctx, sysView, null);
}
/**
* System view iterator.
*/
protected Iterator<R> viewIterator(SearchRow first, SearchRow last) {
return sysView.iterator();
}
/** {@inheritDoc} */
@Override public Iterator<Row> getRows(Session ses, SearchRow first, SearchRow last) {
Iterator<R> rows = viewIterator(first, last);
return new Iterator<Row>() {
@Override public boolean hasNext() {
return rows.hasNext();
}
@Override public Row next() {
R row = rows.next();
Value[] data = new Value[sysView.walker().count()];
sysView.walker().visitAll(row, new AttributeWithValueVisitor() {
@Override public <T> void accept(int idx, String name, Class<T> clazz, @Nullable T val) {
if (val == null)
data[idx] = ValueNull.INSTANCE;
else
data[idx] = CLS_TO_VAL.getOrDefault(clazz, DFLT_FUNC).apply(val);
}
@Override public void acceptBoolean(int idx, String name, boolean val) {
data[idx] = ValueBoolean.get(val);
}
@Override public void acceptChar(int idx, String name, char val) {
data[idx] = ValueString.get(Character.toString(val));
}
@Override public void acceptByte(int idx, String name, byte val) {
data[idx] = ValueByte.get(val);
}
@Override public void acceptShort(int idx, String name, short val) {
data[idx] = ValueShort.get(val);
}
@Override public void acceptInt(int idx, String name, int val) {
data[idx] = ValueInt.get(val);
}
@Override public void acceptLong(int idx, String name, long val) {
data[idx] = ValueLong.get(val);
}
@Override public void acceptFloat(int idx, String name, float val) {
data[idx] = ValueFloat.get(val);
}
@Override public void acceptDouble(int idx, String name, double val) {
data[idx] = ValueDouble.get(val);
}
});
return createRow(ses, data);
}
};
}
/**
* Extract column array for specific {@link SystemView}.
*
* @param sysView System view.
* @param <R> Row type.
* @return SQL column array for {@code sysView}.
*/
private static <R> Column[] columnsList(SystemView<R> sysView) {
Column[] cols = new Column[sysView.walker().count()];
sysView.walker().visitAll(new AttributeVisitor() {
@Override public <T> void accept(int idx, String name, Class<T> clazz) {
int type = CLS_TO_VAL_TYPE.getOrDefault(clazz, Value.STRING);
cols[idx] = newColumn(toSqlName(name), type);
}
});
return cols;
}
/** {@inheritDoc} */
@Override public long getRowCount() {
return sysView.size();
}
/** {@inheritDoc} */
@Override public long getRowCountApproximation() {
// getRowCount() method is not really fast, for some system views it's required to iterate over elements to
// calculate size, so it's more safe to use constant here.
return DEFAULT_ROW_COUNT_APPROXIMATION;
}
/** {@inheritDoc} */
@Override public boolean canGetRowCount() {
return true;
}
}