public static SubordPropPlan getJoinProps(ExprNode filterExpr, int outsideStreamCount, EventType[] allStreamTypesZeroIndexed)
{
// No filter expression means full table scan
if (filterExpr == null)
{
return new SubordPropPlan();
}
// analyze query graph
QueryGraph queryGraph = new QueryGraph(outsideStreamCount + 1);
FilterExprAnalyzer.analyze(filterExpr, queryGraph, false);
// Build a list of streams and indexes
LinkedHashMap<String, SubordPropHashKey> joinProps = new LinkedHashMap<String, SubordPropHashKey>();
LinkedHashMap<String, SubordPropRangeKey> rangeProps = new LinkedHashMap<String, SubordPropRangeKey>();
for (int stream = 0; stream < outsideStreamCount; stream++)
{
int lookupStream = stream + 1;
QueryGraphValue queryGraphValue = queryGraph.getGraphValue(lookupStream, 0);
QueryGraphValuePairHashKeyIndex hashKeysAndIndexes = queryGraphValue.getHashKeyProps();
// handle key-lookups
List<QueryGraphValueEntryHashKeyed> keyPropertiesJoin = hashKeysAndIndexes.getKeys();
String[] indexPropertiesJoin = hashKeysAndIndexes.getIndexed();
if (!keyPropertiesJoin.isEmpty())
{
if (keyPropertiesJoin.size() != indexPropertiesJoin.length)
{
throw new IllegalStateException("Invalid query key and index property collection for stream " + stream);
}
for (int i = 0; i < keyPropertiesJoin.size(); i++)
{
QueryGraphValueEntryHashKeyed keyDesc = keyPropertiesJoin.get(i);
ExprNode compareNode = keyDesc.getKeyExpr();
Class keyPropType = JavaClassHelper.getBoxedType(compareNode.getExprEvaluator().getType());
Class indexedPropType = JavaClassHelper.getBoxedType(allStreamTypesZeroIndexed[0].getPropertyType(indexPropertiesJoin[i]));
Class coercionType = indexedPropType;
if (keyPropType != indexedPropType)
{
coercionType = JavaClassHelper.getCompareToCoercionType(keyPropType, indexedPropType);
}
SubordPropHashKey desc;
if (keyPropertiesJoin.get(i) instanceof QueryGraphValueEntryHashKeyedExpr) {
QueryGraphValueEntryHashKeyedExpr keyExpr = (QueryGraphValueEntryHashKeyedExpr) keyPropertiesJoin.get(i);
Integer keyStreamNum = keyExpr.isRequiresKey() ? stream : null;
desc = new SubordPropHashKey(keyDesc, keyStreamNum, coercionType);
}
else {
QueryGraphValueEntryHashKeyedProp prop = (QueryGraphValueEntryHashKeyedProp) keyDesc;
desc = new SubordPropHashKey(prop, stream, coercionType);
}
joinProps.put(indexPropertiesJoin[i], desc);
}
}
// handle range lookups
QueryGraphValuePairRangeIndex rangeKeysAndIndexes = queryGraphValue.getRangeProps();
String[] rangeIndexes = rangeKeysAndIndexes.getIndexed();
List<QueryGraphValueEntryRange> rangeDescs = rangeKeysAndIndexes.getKeys();
if (rangeDescs.isEmpty()) {
continue;
}
// get all ranges lookups
int count = -1;
for (QueryGraphValueEntryRange rangeDesc : rangeDescs) {
count++;
String rangeIndexProp = rangeIndexes[count];
SubordPropRangeKey subqRangeDesc = rangeProps.get(rangeIndexProp);
// other streams may specify the start or end endpoint of a range, therefore this operation can be additive
if (subqRangeDesc != null) {
if (subqRangeDesc.getRangeInfo().getType().isRange()) {
continue;
}
// see if we can make this additive by using a range
QueryGraphValueEntryRangeRelOp relOpOther = (QueryGraphValueEntryRangeRelOp) subqRangeDesc.getRangeInfo();
QueryGraphValueEntryRangeRelOp relOpThis = (QueryGraphValueEntryRangeRelOp) rangeDesc;
QueryGraphRangeConsolidateDesc opsDesc = QueryGraphRangeUtil.getCanConsolidate(relOpThis.getType(), relOpOther.getType());
if (opsDesc != null) {
ExprNode start;
ExprNode end;
int streamNumStart;
int streamNumEnd;
if (!opsDesc.isReverse()) {
start = relOpOther.getExpression();
end = relOpThis.getExpression();
streamNumEnd = stream;
}
else {
start = relOpThis.getExpression();
streamNumStart = stream;
end = relOpOther.getExpression();
}
boolean allowRangeReversal = relOpOther.isBetweenPart() && relOpThis.isBetweenPart();
QueryGraphValueEntryRangeIn rangeIn = new QueryGraphValueEntryRangeIn(opsDesc.getType(), start, end, allowRangeReversal);
Class indexedPropType = JavaClassHelper.getBoxedType(allStreamTypesZeroIndexed[0].getPropertyType(rangeIndexProp));
Class coercionType = indexedPropType;
Class proposedType = CoercionUtil.getCoercionTypeRangeIn(indexedPropType, rangeIn.getExprStart(), rangeIn.getExprEnd());
if (proposedType != null && proposedType != indexedPropType)
{
coercionType = proposedType;
}
subqRangeDesc = new SubordPropRangeKey(rangeIn, coercionType);
rangeProps.put(rangeIndexProp, subqRangeDesc);
}
// ignore
continue;
}
// an existing entry has not been found
if (rangeDesc.getType().isRange()) {
QueryGraphValueEntryRangeIn rangeIn = (QueryGraphValueEntryRangeIn) rangeDesc;
Class indexedPropType = JavaClassHelper.getBoxedType(allStreamTypesZeroIndexed[0].getPropertyType(rangeIndexProp));
Class coercionType = indexedPropType;
Class proposedType = CoercionUtil.getCoercionTypeRangeIn(indexedPropType, rangeIn.getExprStart(), rangeIn.getExprEnd());
if (proposedType != null && proposedType != indexedPropType)
{
coercionType = proposedType;
}
subqRangeDesc = new SubordPropRangeKey(rangeDesc, coercionType);
}
else {
QueryGraphValueEntryRangeRelOp relOp = (QueryGraphValueEntryRangeRelOp) rangeDesc;
Class keyPropType = relOp.getExpression().getExprEvaluator().getType();
Class indexedPropType = JavaClassHelper.getBoxedType(allStreamTypesZeroIndexed[0].getPropertyType(rangeIndexProp));
Class coercionType = indexedPropType;
if (keyPropType != indexedPropType)
{
coercionType = JavaClassHelper.getCompareToCoercionType(keyPropType, indexedPropType);
}
subqRangeDesc = new SubordPropRangeKey(rangeDesc, coercionType);
}
rangeProps.put(rangeIndexProp, subqRangeDesc);
}
}
return new SubordPropPlan(joinProps, rangeProps);
}