/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed 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 com.linkedin.pinot.tools.scan.query; import com.linkedin.pinot.core.common.BlockMultiValIterator; import com.linkedin.pinot.core.common.BlockSingleValIterator; import com.linkedin.pinot.core.query.utils.Pair; import com.linkedin.pinot.core.segment.index.ColumnMetadata; import com.linkedin.pinot.core.segment.index.IndexSegmentImpl; import com.linkedin.pinot.core.segment.index.SegmentMetadataImpl; import com.linkedin.pinot.core.segment.index.readers.Dictionary; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.ArrayUtils; public class Projection { private final IndexSegmentImpl _indexSegment; private final SegmentMetadataImpl _metadata; private final List<Integer> _filteredDocIds; private final List<Pair> _columnList; private final Set<String> _mvColumns; private final Map<String, int[]> _mvColumnArrayMap; private Map<String, Dictionary> _dictionaryMap; private boolean _addCountStar; private int _limit = 10; Projection(IndexSegmentImpl indexSegment, SegmentMetadataImpl metadata, List<Integer> filteredDocIds, List<Pair> columns, Map<String, Dictionary> dictionaryMap, boolean addCountStar) { _indexSegment = indexSegment; _metadata = metadata; _filteredDocIds = filteredDocIds; _dictionaryMap = dictionaryMap; _addCountStar = addCountStar; _columnList = new ArrayList<>(); for (Pair pair : columns) { _columnList.add(pair); } _mvColumns = new HashSet<>(); _mvColumnArrayMap = new HashMap<>(); for (ColumnMetadata columnMetadata : _metadata.getColumnMetadataMap().values()) { String column = columnMetadata.getColumnName(); if (!columnMetadata.isSingleValue()) { _mvColumns.add(column); } _mvColumnArrayMap.put(column, new int[columnMetadata.getMaxNumberOfMultiValues()]); } } public ResultTable run() { ResultTable resultTable = new ResultTable(_columnList, _filteredDocIds.size()); resultTable.setResultType(ResultTable.ResultType.Selection); for (Pair pair : _columnList) { String column = (String) pair.getFirst(); if (!_mvColumns.contains(column)) { BlockSingleValIterator bvIter = (BlockSingleValIterator) _indexSegment.getDataSource(column).getNextBlock().getBlockValueSet().iterator(); int rowId = 0; for (Integer docId : _filteredDocIds) { bvIter.skipTo(docId); resultTable.add(rowId++, bvIter.nextIntVal()); } } else { BlockMultiValIterator bvIter = (BlockMultiValIterator) _indexSegment.getDataSource(column).getNextBlock().getBlockValueSet().iterator(); int rowId = 0; for (Integer docId : _filteredDocIds) { bvIter.skipTo(docId); int[] dictIds = _mvColumnArrayMap.get(column); int numMVValues = bvIter.nextIntVal(dictIds); dictIds = Arrays.copyOf(dictIds, numMVValues); resultTable.add(rowId++, ArrayUtils.toObject(dictIds)); } } } return transformFromIdToValues(resultTable, _dictionaryMap, _addCountStar); } public ResultTable transformFromIdToValues(ResultTable resultTable, Map<String, Dictionary> dictionaryMap, boolean addCountStar) { List<Pair> columnList = resultTable.getColumnList(); for (ResultTable.Row row : resultTable) { int colId = 0; for (Object object : row) { String column = (String) columnList.get(colId).getFirst(); Dictionary dictionary = dictionaryMap.get(column); if (object instanceof Object[]) { Object[] objArray = (Object[]) object; Object[] valArray = new Object[objArray.length]; for (int i = 0; i < objArray.length; ++i) { int dictId = (int) objArray[i]; valArray[i] = dictionary.get(dictId); } row.set(colId, valArray); } else { int dictId = (int) object; row.set(colId, dictionary.get(dictId)); } ++colId; } } // Add additional column for count(*) if (addCountStar) { for (ResultTable.Row row : resultTable) { row.add(1); } resultTable.addCountStarColumn(); } return resultTable; } }