/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.epl.join.plan;
import com.espertech.esper.epl.index.service.EventAdvancedIndexProvisionDesc;
import com.espertech.esper.epl.lookup.IndexMultiKey;
import com.espertech.esper.epl.lookup.IndexedPropDesc;
import com.espertech.esper.util.CollectionUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Specifies an index to build as part of an overall query plan.
*/
public class QueryPlanIndexItem {
private final String[] indexProps;
private Class[] optIndexCoercionTypes;
private final String[] rangeProps;
private final Class[] optRangeCoercionTypes;
private final boolean unique;
private final EventAdvancedIndexProvisionDesc advancedIndexProvisionDesc;
/**
* Ctor.
*
* @param indexProps - array of property names with the first dimension suplying the number of
* distinct indexes. The second dimension can be empty and indicates a full table scan.
* @param optIndexCoercionTypes - array of coercion types for each index, or null entry for no coercion required
* @param rangeProps range props
* @param optRangeCoercionTypes coercion for ranges
* @param unique whether index is unique on index props (not applicable to range-only)
* @param advancedIndexProvisionDesc advanced indexes
*/
public QueryPlanIndexItem(String[] indexProps, Class[] optIndexCoercionTypes, String[] rangeProps, Class[] optRangeCoercionTypes, boolean unique, EventAdvancedIndexProvisionDesc advancedIndexProvisionDesc) {
if (advancedIndexProvisionDesc == null) {
if (unique && indexProps.length == 0) {
throw new IllegalArgumentException("Invalid unique index planned without hash index props");
}
if (unique && rangeProps.length > 0) {
throw new IllegalArgumentException("Invalid unique index planned that includes range props");
}
}
this.indexProps = indexProps;
this.optIndexCoercionTypes = optIndexCoercionTypes;
this.rangeProps = (rangeProps == null || rangeProps.length == 0) ? null : rangeProps;
this.optRangeCoercionTypes = optRangeCoercionTypes;
this.unique = unique;
this.advancedIndexProvisionDesc = advancedIndexProvisionDesc;
}
public QueryPlanIndexItem(List<IndexedPropDesc> hashProps, List<IndexedPropDesc> btreeProps, boolean unique, EventAdvancedIndexProvisionDesc advancedIndexProvisionDesc) {
this(getNames(hashProps), getTypes(hashProps), getNames(btreeProps), getTypes(btreeProps), unique, advancedIndexProvisionDesc);
}
public String[] getIndexProps() {
return indexProps;
}
public Class[] getOptIndexCoercionTypes() {
return optIndexCoercionTypes;
}
public String[] getRangeProps() {
return rangeProps;
}
public Class[] getOptRangeCoercionTypes() {
return optRangeCoercionTypes;
}
public void setOptIndexCoercionTypes(Class[] optIndexCoercionTypes) {
this.optIndexCoercionTypes = optIndexCoercionTypes;
}
public boolean isUnique() {
return unique;
}
public EventAdvancedIndexProvisionDesc getAdvancedIndexProvisionDesc() {
return advancedIndexProvisionDesc;
}
@Override
public String toString() {
return "QueryPlanIndexItem{" +
"unique=" + unique +
", indexProps=" + (indexProps == null ? null : Arrays.asList(indexProps)) +
", rangeProps=" + (rangeProps == null ? null : Arrays.asList(rangeProps)) +
", optIndexCoercionTypes=" + (optIndexCoercionTypes == null ? null : Arrays.asList(optIndexCoercionTypes)) +
", optRangeCoercionTypes=" + (optRangeCoercionTypes == null ? null : Arrays.asList(optRangeCoercionTypes)) +
", advanced=" + (advancedIndexProvisionDesc == null ? null : advancedIndexProvisionDesc.getIndexDesc().getIndexTypeName()) +
"}";
}
public boolean equalsCompareSortedProps(QueryPlanIndexItem other) {
if (unique != other.unique) {
return false;
}
String[] otherIndexProps = CollectionUtil.copySortArray(other.getIndexProps());
String[] thisIndexProps = CollectionUtil.copySortArray(this.getIndexProps());
String[] otherRangeProps = CollectionUtil.copySortArray(other.getRangeProps());
String[] thisRangeProps = CollectionUtil.copySortArray(this.getRangeProps());
boolean compared = CollectionUtil.compare(otherIndexProps, thisIndexProps) && CollectionUtil.compare(otherRangeProps, thisRangeProps);
return compared && advancedIndexProvisionDesc == null && other.advancedIndexProvisionDesc == null;
}
public List<IndexedPropDesc> getHashPropsAsList() {
return asList(indexProps, optIndexCoercionTypes);
}
public List<IndexedPropDesc> getBtreePropsAsList() {
return asList(rangeProps, optRangeCoercionTypes);
}
private List<IndexedPropDesc> asList(String[] props, Class[] types) {
if (props == null || props.length == 0) {
return Collections.emptyList();
}
List<IndexedPropDesc> list = new ArrayList<>(props.length);
for (int i = 0; i < props.length; i++) {
list.add(new IndexedPropDesc(props[i], types[i]));
}
return list;
}
private static String[] getNames(IndexedPropDesc[] props) {
String[] names = new String[props.length];
for (int i = 0; i < props.length; i++) {
names[i] = props[i].getIndexPropName();
}
return names;
}
private static Class[] getTypes(IndexedPropDesc[] props) {
Class[] types = new Class[props.length];
for (int i = 0; i < props.length; i++) {
types[i] = props[i].getCoercionType();
}
return types;
}
private static String[] getNames(List<IndexedPropDesc> props) {
String[] names = new String[props.size()];
for (int i = 0; i < props.size(); i++) {
names[i] = props.get(i).getIndexPropName();
}
return names;
}
private static Class[] getTypes(List<IndexedPropDesc> props) {
Class[] types = new Class[props.size()];
for (int i = 0; i < props.size(); i++) {
types[i] = props.get(i).getCoercionType();
}
return types;
}
public static QueryPlanIndexItem fromIndexMultikeyTablePrimaryKey(IndexMultiKey indexMultiKey) {
return new QueryPlanIndexItem(
getNames(indexMultiKey.getHashIndexedProps()),
getTypes(indexMultiKey.getHashIndexedProps()),
getNames(indexMultiKey.getRangeIndexedProps()),
getTypes(indexMultiKey.getRangeIndexedProps()),
indexMultiKey.isUnique(), null);
}
}