/**
* 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.util;
import com.google.gson.Gson;
import org.apache.tajo.catalog.Column;
import org.apache.tajo.catalog.Schema;
import org.apache.tajo.catalog.SortSpec;
import org.apache.tajo.datum.Datum;
import org.apache.tajo.engine.eval.*;
import org.apache.tajo.engine.json.CoreGsonHelper;
import org.apache.tajo.engine.planner.LogicalPlan;
import org.apache.tajo.engine.planner.logical.IndexScanNode;
import org.apache.tajo.engine.planner.logical.ScanNode;
import org.apache.tajo.storage.fragment.FileFragment;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
public class IndexUtil {
public static String getIndexNameOfFrag(FileFragment fragment, SortSpec[] keys) {
StringBuilder builder = new StringBuilder();
builder.append(fragment.getPath().getName() + "_");
builder.append(fragment.getStartKey() + "_" + fragment.getEndKey() + "_");
for(int i = 0 ; i < keys.length ; i ++) {
builder.append(keys[i].getSortKey().getSimpleName()+"_");
}
builder.append("_index");
return builder.toString();
}
public static String getIndexName(String indexName , SortSpec[] keys) {
StringBuilder builder = new StringBuilder();
builder.append(indexName + "_");
for(int i = 0 ; i < keys.length ; i ++) {
builder.append(keys[i].getSortKey().getSimpleName() + "_");
}
return builder.toString();
}
public static IndexScanNode indexEval(LogicalPlan plan, ScanNode scanNode,
Iterator<Entry<String, String>> iter ) {
EvalNode qual = scanNode.getQual();
Gson gson = CoreGsonHelper.getInstance();
FieldAndValueFinder nodeFinder = new FieldAndValueFinder();
qual.preOrder(nodeFinder);
LinkedList<EvalNode> nodeList = nodeFinder.getNodeList();
int maxSize = Integer.MIN_VALUE;
SortSpec[] maxIndex = null;
String json;
while(iter.hasNext()) {
Entry<String , String> entry = iter.next();
json = entry.getValue();
SortSpec[] sortKey = gson.fromJson(json, SortSpec[].class);
if(sortKey.length > nodeList.size()) {
/* If the number of the sort key is greater than where condition,
* this index cannot be used
* */
continue;
} else {
boolean[] equal = new boolean[sortKey.length];
for(int i = 0 ; i < sortKey.length ; i ++) {
for(int j = 0 ; j < nodeList.size() ; j ++) {
Column col = ((FieldEval)(nodeList.get(j).getLeftExpr())).getColumnRef();
if(col.equals(sortKey[i].getSortKey())) {
equal[i] = true;
}
}
}
boolean chk = true;
for(int i = 0 ; i < equal.length ; i ++) {
chk = chk && equal[i];
}
if(chk) {
if(maxSize < sortKey.length) {
maxSize = sortKey.length;
maxIndex = sortKey;
}
}
}
}
if(maxIndex == null) {
return null;
} else {
Schema keySchema = new Schema();
for(int i = 0 ; i < maxIndex.length ; i ++ ) {
keySchema.addColumn(maxIndex[i].getSortKey());
}
Datum[] datum = new Datum[nodeList.size()];
for(int i = 0 ; i < nodeList.size() ; i ++ ) {
datum[i] = ((ConstEval)(nodeList.get(i).getRightExpr())).getValue();
}
return new IndexScanNode(plan.newPID(), scanNode, keySchema , datum , maxIndex);
}
}
private static class FieldAndValueFinder implements EvalNodeVisitor {
private LinkedList<EvalNode> nodeList = new LinkedList<EvalNode>();
public LinkedList<EvalNode> getNodeList () {
return this.nodeList;
}
@Override
public void visit(EvalNode node) {
switch(node.getType()) {
case AND:
break;
case EQUAL:
if( node.getLeftExpr().getType() == EvalType.FIELD
&& node.getRightExpr().getType() == EvalType.CONST ) {
nodeList.add(node);
}
break;
case IS_NULL:
if( node.getLeftExpr().getType() == EvalType.FIELD
&& node.getRightExpr().getType() == EvalType.CONST) {
nodeList.add(node);
}
}
}
}
}