use of org.apache.hyracks.algebricks.common.utils.ListSet in project asterixdb by apache.
the class FDsAndEquivClassesVisitor method visitDistinctOperator.
@Override
public Void visitDistinctOperator(DistinctOperator op, IOptimizationContext ctx) throws AlgebricksException {
ILogicalOperator op0 = op.getInputs().get(0).getValue();
List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>();
ctx.putFDList(op, functionalDependencies);
for (FunctionalDependency inherited : getOrComputeFDs(op0, ctx)) {
boolean isCoveredByDistinctByVars = true;
for (LogicalVariable v : inherited.getHead()) {
if (!op.isDistinctByVar(v)) {
isCoveredByDistinctByVars = false;
}
}
if (isCoveredByDistinctByVars) {
List<LogicalVariable> newTail = new ArrayList<LogicalVariable>();
for (LogicalVariable v2 : inherited.getTail()) {
if (op.isDistinctByVar(v2)) {
newTail.add(v2);
}
}
if (!newTail.isEmpty()) {
List<LogicalVariable> newHead = new ArrayList<LogicalVariable>(inherited.getHead());
FunctionalDependency newFd = new FunctionalDependency(newHead, newTail);
functionalDependencies.add(newFd);
}
}
}
Set<LogicalVariable> gbySet = new HashSet<LogicalVariable>();
List<Mutable<ILogicalExpression>> expressions = op.getExpressions();
for (Mutable<ILogicalExpression> pRef : expressions) {
ILogicalExpression p = pRef.getValue();
if (p.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
VariableReferenceExpression v = (VariableReferenceExpression) p;
gbySet.add(v.getVariableReference());
}
}
LocalGroupingProperty lgp = new LocalGroupingProperty(gbySet);
Map<LogicalVariable, EquivalenceClass> equivalenceClasses = getOrComputeEqClasses(op0, ctx);
ctx.putEquivalenceClassMap(op, equivalenceClasses);
ILocalStructuralProperty normalizedLgp = lgp.normalize(equivalenceClasses, functionalDependencies);
Set<LogicalVariable> normSet = new ListSet<>();
normalizedLgp.getColumns(normSet);
List<Mutable<ILogicalExpression>> newDistinctByList = new ArrayList<Mutable<ILogicalExpression>>();
for (Mutable<ILogicalExpression> p2Ref : expressions) {
ILogicalExpression p2 = p2Ref.getValue();
if (p2.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
VariableReferenceExpression var2 = (VariableReferenceExpression) p2;
LogicalVariable v2 = var2.getVariableReference();
if (normSet.contains(v2)) {
newDistinctByList.add(p2Ref);
}
} else {
newDistinctByList.add(p2Ref);
}
}
expressions.clear();
expressions.addAll(newDistinctByList);
return null;
}
use of org.apache.hyracks.algebricks.common.utils.ListSet in project asterixdb by apache.
the class IntroduceGroupByForSubplanRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op0 = (AbstractLogicalOperator) opRef.getValue();
if (op0.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
return false;
}
SubplanOperator subplan = (SubplanOperator) op0;
Iterator<ILogicalPlan> plansIter = subplan.getNestedPlans().iterator();
ILogicalPlan p = null;
while (plansIter.hasNext()) {
p = plansIter.next();
}
if (p == null) {
return false;
}
if (p.getRoots().size() != 1) {
return false;
}
Mutable<ILogicalOperator> subplanRoot = p.getRoots().get(0);
AbstractLogicalOperator op1 = (AbstractLogicalOperator) subplanRoot.getValue();
Mutable<ILogicalOperator> botRef = subplanRoot;
AbstractLogicalOperator op2;
// Project is optional
if (op1.getOperatorTag() != LogicalOperatorTag.PROJECT) {
op2 = op1;
} else {
ProjectOperator project = (ProjectOperator) op1;
botRef = project.getInputs().get(0);
op2 = (AbstractLogicalOperator) botRef.getValue();
}
if (op2.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator aggregate = (AggregateOperator) op2;
Set<LogicalVariable> free = new HashSet<LogicalVariable>();
VariableUtilities.getUsedVariables(aggregate, free);
Mutable<ILogicalOperator> op3Ref = aggregate.getInputs().get(0);
AbstractLogicalOperator op3 = (AbstractLogicalOperator) op3Ref.getValue();
while (op3.getInputs().size() == 1) {
Set<LogicalVariable> prod = new HashSet<LogicalVariable>();
VariableUtilities.getProducedVariables(op3, prod);
free.removeAll(prod);
VariableUtilities.getUsedVariables(op3, free);
botRef = op3Ref;
op3Ref = op3.getInputs().get(0);
op3 = (AbstractLogicalOperator) op3Ref.getValue();
}
if (op3.getOperatorTag() != LogicalOperatorTag.INNERJOIN && op3.getOperatorTag() != LogicalOperatorTag.LEFTOUTERJOIN) {
return false;
}
AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) op3;
if (join.getCondition().getValue() == ConstantExpression.TRUE) {
return false;
}
VariableUtilities.getUsedVariables(join, free);
AbstractLogicalOperator b0 = (AbstractLogicalOperator) join.getInputs().get(0).getValue();
// see if there's an NTS at the end of the pipeline
NestedTupleSourceOperator outerNts = getNts(b0);
if (outerNts == null) {
AbstractLogicalOperator b1 = (AbstractLogicalOperator) join.getInputs().get(1).getValue();
outerNts = getNts(b1);
if (outerNts == null) {
return false;
}
}
Set<LogicalVariable> pkVars = computeGbyVars(outerNts, free, context);
if (pkVars == null || pkVars.size() < 1) {
// there is no non-trivial primary key, group-by keys are all live variables
// that were produced by descendant or self
ILogicalOperator subplanInput = subplan.getInputs().get(0).getValue();
pkVars = new HashSet<LogicalVariable>();
//get live variables
VariableUtilities.getLiveVariables(subplanInput, pkVars);
//get produced variables
Set<LogicalVariable> producedVars = new HashSet<LogicalVariable>();
VariableUtilities.getProducedVariablesInDescendantsAndSelf(subplanInput, producedVars);
//retain the intersection
pkVars.retainAll(producedVars);
}
AlgebricksConfig.ALGEBRICKS_LOGGER.fine("Found FD for introducing group-by: " + pkVars);
Mutable<ILogicalOperator> rightRef = join.getInputs().get(1);
LogicalVariable testForNull = null;
AbstractLogicalOperator right = (AbstractLogicalOperator) rightRef.getValue();
switch(right.getOperatorTag()) {
case UNNEST:
{
UnnestOperator innerUnnest = (UnnestOperator) right;
// Select [ $y != null ]
testForNull = innerUnnest.getVariable();
break;
}
case RUNNINGAGGREGATE:
{
ILogicalOperator inputToRunningAggregate = right.getInputs().get(0).getValue();
Set<LogicalVariable> producedVars = new ListSet<LogicalVariable>();
VariableUtilities.getProducedVariables(inputToRunningAggregate, producedVars);
if (!producedVars.isEmpty()) {
// Select [ $y != null ]
testForNull = producedVars.iterator().next();
}
break;
}
case DATASOURCESCAN:
{
DataSourceScanOperator innerScan = (DataSourceScanOperator) right;
// Select [ $y != null ]
if (innerScan.getVariables().size() == 1) {
testForNull = innerScan.getVariables().get(0);
}
break;
}
default:
break;
}
if (testForNull == null) {
testForNull = context.newVar();
AssignOperator tmpAsgn = new AssignOperator(testForNull, new MutableObject<ILogicalExpression>(ConstantExpression.TRUE));
tmpAsgn.getInputs().add(new MutableObject<ILogicalOperator>(rightRef.getValue()));
rightRef.setValue(tmpAsgn);
context.computeAndSetTypeEnvironmentForOperator(tmpAsgn);
}
IFunctionInfo finfoEq = context.getMetadataProvider().lookupFunction(AlgebricksBuiltinFunctions.IS_MISSING);
ILogicalExpression isNullTest = new ScalarFunctionCallExpression(finfoEq, new MutableObject<ILogicalExpression>(new VariableReferenceExpression(testForNull)));
IFunctionInfo finfoNot = context.getMetadataProvider().lookupFunction(AlgebricksBuiltinFunctions.NOT);
ScalarFunctionCallExpression nonNullTest = new ScalarFunctionCallExpression(finfoNot, new MutableObject<ILogicalExpression>(isNullTest));
SelectOperator selectNonNull = new SelectOperator(new MutableObject<ILogicalExpression>(nonNullTest), false, null);
GroupByOperator g = new GroupByOperator();
Mutable<ILogicalOperator> newSubplanRef = new MutableObject<ILogicalOperator>(subplan);
NestedTupleSourceOperator nts = new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(g));
opRef.setValue(g);
selectNonNull.getInputs().add(new MutableObject<ILogicalOperator>(nts));
List<Mutable<ILogicalOperator>> prodInpList = botRef.getValue().getInputs();
prodInpList.clear();
prodInpList.add(new MutableObject<ILogicalOperator>(selectNonNull));
ILogicalPlan gPlan = new ALogicalPlanImpl(new MutableObject<ILogicalOperator>(subplanRoot.getValue()));
g.getNestedPlans().add(gPlan);
subplanRoot.setValue(op3Ref.getValue());
g.getInputs().add(newSubplanRef);
HashSet<LogicalVariable> underVars = new HashSet<LogicalVariable>();
VariableUtilities.getLiveVariables(subplan.getInputs().get(0).getValue(), underVars);
underVars.removeAll(pkVars);
Map<LogicalVariable, LogicalVariable> mappedVars = buildVarExprList(pkVars, context, g, g.getGroupByList());
context.updatePrimaryKeys(mappedVars);
for (LogicalVariable uv : underVars) {
g.getDecorList().add(new Pair<LogicalVariable, Mutable<ILogicalExpression>>(null, new MutableObject<ILogicalExpression>(new VariableReferenceExpression(uv))));
}
OperatorPropertiesUtil.typeOpRec(subplanRoot, context);
OperatorPropertiesUtil.typeOpRec(gPlan.getRoots().get(0), context);
context.computeAndSetTypeEnvironmentForOperator(g);
return true;
}
use of org.apache.hyracks.algebricks.common.utils.ListSet in project asterixdb by apache.
the class BTreeSearchPOperator method getRequiredPropertiesForChildren.
@Override
public PhysicalRequirements getRequiredPropertiesForChildren(ILogicalOperator op, IPhysicalPropertiesVector reqdByParent, IOptimizationContext context) {
if (requiresBroadcast) {
// For primary indexes optimizing an equality condition we can reduce the broadcast requirement to hash partitioning.
if (isPrimaryIndex && isEqCondition) {
// If this is a composite primary index, then all of the keys should be provided.
Index searchIndex = ((DataSourceIndex) idx).getIndex();
int numberOfKeyFields = searchIndex.getKeyFieldNames().size();
if (numberOfKeyFields < 2 || (lowKeyVarList.size() == numberOfKeyFields && highKeyVarList.size() == numberOfKeyFields)) {
StructuralPropertiesVector[] pv = new StructuralPropertiesVector[1];
ListSet<LogicalVariable> searchKeyVars = new ListSet<>();
searchKeyVars.addAll(lowKeyVarList);
searchKeyVars.addAll(highKeyVarList);
// Also, add a local sorting property to enforce a sort before the primary-index operator.
List<ILocalStructuralProperty> propsLocal = new ArrayList<>();
List<OrderColumn> orderColumns = new ArrayList<>();
for (LogicalVariable orderVar : searchKeyVars) {
orderColumns.add(new OrderColumn(orderVar, OrderKind.ASC));
}
propsLocal.add(new LocalOrderProperty(orderColumns));
pv[0] = new StructuralPropertiesVector(new UnorderedPartitionedProperty(searchKeyVars, domain), propsLocal);
return new PhysicalRequirements(pv, IPartitioningRequirementsCoordinator.NO_COORDINATION);
}
}
StructuralPropertiesVector[] pv = new StructuralPropertiesVector[1];
pv[0] = new StructuralPropertiesVector(new BroadcastPartitioningProperty(domain), null);
return new PhysicalRequirements(pv, IPartitioningRequirementsCoordinator.NO_COORDINATION);
} else {
return super.getRequiredPropertiesForChildren(op, reqdByParent, context);
}
}
use of org.apache.hyracks.algebricks.common.utils.ListSet in project asterixdb by apache.
the class RemoveRedundantListifyRule method applyRuleDown.
private boolean applyRuleDown(Mutable<ILogicalOperator> opRef, Set<LogicalVariable> varSet, IOptimizationContext context) throws AlgebricksException {
boolean changed = applies(opRef, varSet, context);
changed |= appliesForReverseCase(opRef, varSet, context);
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
VariableUtilities.getUsedVariables(op, varSet);
if (op.hasNestedPlans()) {
// Variables used by the parent operators should be live at op.
Set<LogicalVariable> localLiveVars = new ListSet<LogicalVariable>();
VariableUtilities.getLiveVariables(op, localLiveVars);
varSet.retainAll(localLiveVars);
AbstractOperatorWithNestedPlans aonp = (AbstractOperatorWithNestedPlans) op;
for (ILogicalPlan p : aonp.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
if (applyRuleDown(r, varSet, context)) {
changed = true;
}
context.addToDontApplySet(this, r.getValue());
}
}
}
for (Mutable<ILogicalOperator> i : op.getInputs()) {
if (applyRuleDown(i, varSet, context)) {
changed = true;
}
context.addToDontApplySet(this, i.getValue());
}
return changed;
}
use of org.apache.hyracks.algebricks.common.utils.ListSet in project asterixdb by apache.
the class PropertiesUtil method matchNormalizedLocalProperties.
// Checks whether normalized delivered properties can satisfy normalized required property.
private static boolean matchNormalizedLocalProperties(List<ILocalStructuralProperty> reqs, List<ILocalStructuralProperty> dlvds) {
boolean hasOrderPropertyInReq = false;
boolean hasGroupingPropertyInReq = false;
boolean orderPropertyMet = false;
boolean groupingPropertyMet = false;
for (ILocalStructuralProperty req : reqs) {
PropertyType reqType = req.getPropertyType();
hasOrderPropertyInReq |= reqType == PropertyType.LOCAL_ORDER_PROPERTY;
hasGroupingPropertyInReq |= reqType == PropertyType.LOCAL_GROUPING_PROPERTY;
for (ILocalStructuralProperty dlvd : dlvds) {
PropertyType dlvdType = dlvd.getPropertyType();
if (reqType == PropertyType.LOCAL_ORDER_PROPERTY && dlvdType != PropertyType.LOCAL_ORDER_PROPERTY) {
// property.
continue;
}
if (reqType == PropertyType.LOCAL_ORDER_PROPERTY) {
LocalOrderProperty lop = (LocalOrderProperty) dlvd;
// It is enough that one required ordering property is met.
orderPropertyMet |= lop.implies(req);
} else {
Set<LogicalVariable> reqdCols = new ListSet<>();
Set<LogicalVariable> dlvdCols = new ListSet<>();
req.getColumns(reqdCols);
dlvd.getColumns(dlvdCols);
// It is enough that one required grouping property is met.
groupingPropertyMet |= isPrefixOf(reqdCols.iterator(), dlvdCols.iterator());
}
}
}
// satisfied and one of required grouping properties is satisfied.
return (!hasOrderPropertyInReq || orderPropertyMet) && (!hasGroupingPropertyInReq || groupingPropertyMet);
}
Aggregations