/**
* 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.tajo.engine.utils;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tajo.catalog.Column;
import org.apache.tajo.catalog.Schema;
import org.apache.tajo.catalog.SortSpec;
import org.apache.tajo.catalog.statistics.ColumnStats;
import org.apache.tajo.datum.DatumFactory;
import org.apache.tajo.datum.NullDatum;
import org.apache.tajo.storage.Tuple;
import org.apache.tajo.storage.TupleRange;
import org.apache.tajo.storage.VTuple;
import java.util.List;
import java.util.Map;
public class TupleUtil {
private static final Log LOG = LogFactory.getLog(TupleUtil.class);
/**
* if max value is null, set ranges[last]
* @param sortSpecs
* @param sortSchema
* @param colStats
* @param ranges
*/
public static void setMaxRangeIfNull(SortSpec[] sortSpecs, Schema sortSchema,
List<ColumnStats> colStats, TupleRange[] ranges) {
Map<Column, ColumnStats> statMap = Maps.newHashMap();
for (ColumnStats stat : colStats) {
statMap.put(stat.getColumn(), stat);
}
int i = 0;
for (Column col : sortSchema.getRootColumns()) {
ColumnStats columnStat = statMap.get(col);
if (columnStat == null) {
continue;
}
if (columnStat.hasNullValue()) {
if (sortSpecs[i].isNullsFirst()) {
Tuple rangeTuple = ranges[0].getStart();
rangeTuple.put(i, NullDatum.get());
} else {
Tuple rangeTuple = ranges[ranges.length - 1].getEnd();
if (LOG.isDebugEnabled()) {
LOG.debug("Set null into range: " + col.getQualifiedName() + ", previous tuple is " + rangeTuple);
}
rangeTuple.put(i, NullDatum.get());
LOG.info("Set null into range: " + col.getQualifiedName() + ", current tuple is " + rangeTuple);
}
}
i++;
}
}
public static TupleRange columnStatToRange(SortSpec [] sortSpecs, Schema target, List<ColumnStats> colStats,
boolean checkNull) {
Map<Column, ColumnStats> statSet = Maps.newHashMap();
for (ColumnStats stat : colStats) {
statSet.put(stat.getColumn(), stat);
}
for (Column col : target.getRootColumns()) {
Preconditions.checkState(statSet.containsKey(col),
"ERROR: Invalid Column Stats (column stats: " + colStats + ", there exists not target " + col);
}
VTuple startTuple = new VTuple(target.size());
VTuple endTuple = new VTuple(target.size());
int i = 0;
int sortSpecIndex = 0;
// In outer join, empty table could be searched.
// As a result, min value and max value would be null.
// So, we should put NullDatum for this case.
for (Column col : target.getRootColumns()) {
if (sortSpecs[sortSpecIndex].isAscending()) {
if (statSet.get(col).getMinValue() != null)
startTuple.put(i, statSet.get(col).getMinValue());
else
startTuple.put(i, DatumFactory.createNullDatum());
if (checkNull) {
if (statSet.get(col).hasNullValue() || statSet.get(col).getMaxValue() == null)
endTuple.put(i, DatumFactory.createNullDatum());
else
endTuple.put(i, statSet.get(col).getMaxValue());
} else {
if (statSet.get(col).getMaxValue() != null)
endTuple.put(i, statSet.get(col).getMaxValue());
else
endTuple.put(i, DatumFactory.createNullDatum());
}
} else {
if (checkNull) {
if (statSet.get(col).hasNullValue() || statSet.get(col).getMaxValue() == null)
startTuple.put(i, DatumFactory.createNullDatum());
else
startTuple.put(i, statSet.get(col).getMaxValue());
} else {
if (statSet.get(col).getMaxValue() != null)
startTuple.put(i, statSet.get(col).getMaxValue());
else
startTuple.put(i, DatumFactory.createNullDatum());
}
if (statSet.get(col).getMinValue() != null)
endTuple.put(i, statSet.get(col).getMinValue());
else
endTuple.put(i, DatumFactory.createNullDatum());
}
if (target.getRootColumns().size() == sortSpecs.length) {
// Not composite column sort
sortSpecIndex++;
}
i++;
}
return new TupleRange(sortSpecs, startTuple, endTuple);
}
}