--- /dev/null
+package org.simantics.scl.compiler.elaboration.query.compilation;
+
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.query.QAtom;
+
+public class RelationConstraint extends QueryConstraint {
+
+ // static
+ QAtom atom;
+
+ int[] optionalVariableByParameter;
+ Variable[] parameters;
+
+ long requiredVariablesMask;
+
+ public RelationConstraint(int[] variables, Variable[] parameters, QAtom atom, int[] optionalVariableByParameter,
+ long requiredVariablesMask) {
+ super(variables);
+ this.atom = atom;
+ this.parameters = parameters;
+ this.optionalVariableByParameter = optionalVariableByParameter;
+ this.requiredVariablesMask = requiredVariablesMask;
+ }
+
+ @Override
+ public boolean canBeSolvedFrom(long boundVariables) {
+ return getSolutionBranching(boundVariables) != Double.POSITIVE_INFINITY;
+ }
+
+ @Override
+ public double getSolutionBranching(long boundVariables) {
+ if( (boundVariables&requiredVariablesMask) != requiredVariablesMask )
+ return Double.POSITIVE_INFINITY;
+ return atom.relation.getSelectivity(getLocalBoundVariables(boundVariables));
+ }
+
+ @Override
+ public double getSolutionCost(long boundVariables) {
+ return 1.0;
+ }
+
+ @Override
+ public void generate(QueryCompilationContext context) {
+ atom.relation.generate(atom.location,
+ context, atom.typeParameters,
+ parameters, getLocalBoundVariables(finalBoundVariables));
+ for(int i=atom.parameters.length-1;i>=0;--i)
+ if(optionalVariableByParameter[i] < 0 && !(atom.parameters[i] instanceof EVariable))
+ context.let(parameters[i], atom.parameters[i]);
+ }
+
+ private int getLocalBoundVariables(long boundVariables) {
+ int localBoundVariables = 0;
+ for(int i=0;i<optionalVariableByParameter.length;++i) {
+ int v = optionalVariableByParameter[i];
+ if(v < 0 || ((boundVariables >> v)&1) != 0)
+ localBoundVariables |= 1 << i;
+ }
+ return localBoundVariables;
+ }
+
+ @Override
+ public String toString() {
+ return atom.toString();
+ }
+}