internal static DbExpression Substitute(DbExpression original, string referencedVariable, Dictionary <string, DbExpression> propertyValues)
            {
                Debug.Assert(original != null, "Original expression cannot be null");
                ValueSubstituter visitor = new ValueSubstituter(referencedVariable, propertyValues);

                return(visitor.VisitExpression(original));
            }
Example #2
0
            internal static DbExpression Substitute(
                DbExpression original, string referencedVariable, Dictionary <string, DbExpression> propertyValues)
            {
                DebugCheck.NotNull(original);
                var visitor = new ValueSubstituter(referencedVariable, propertyValues);

                return(visitor.VisitExpression(original));
            }
Example #3
0
        public void SubstitutionsReplaceReferencedKeys()
        {
            //Arrange
            var refGuids  = GuidArray(3);
            var table1    = _om.Make <SnapshotObjectMother.GuidKeyTable>(GuidArray(4));
            var refTable1 = _om.Make <SnapshotObjectMother.GuidRefTable>((refGuids[0], table1[0].GuidKeyId), (refGuids[1], table1[1].GuidKeyId));

            void TakeSnapshot(string name)
            {
                var builder = _om.NewSnapshot(name);

                table1.ToSnapshotTable(builder);
                refTable1.ToSnapshotTable(builder);
            }

            TakeSnapshot("Before");
            table1[0].Variable           = "edited";
            table1[1].Variable           = "edited";
            refTable1[0].GuidKeyParentId = table1[1].GuidKeyId;
            refTable1[1].GuidKeyParentId = table1[2].GuidKeyId;
            TakeSnapshot("After");

            var before = _om.GetSnapshot("Before");
            var after  = _om.GetSnapshot("After");

            var diffs = DifferenceRegulator.ExpandDifferences(_om.Collection, SnapshotDifferenceCalculator.GetDifferences(_om.Collection, before, after), before);

            var tables            = diffs.Select(d => d.TableDefinition).ToList();
            var unpredictableCols = UnpredictableColumnLocator.Locate(tables);
            var columnValueSets   = unpredictableCols.Select(u => UnpredictableValueScanner.Scan(u, diffs)).ToList();

            //Act
            var result = diffs;

            foreach (var columnValueSet in columnValueSets)
            {
                result = ValueSubstituter.Substitute(columnValueSet, result, _om.Collection);
            }

            //Assert
            var output = new Output();

            result.Report(output);
            output.Report.Verify();
        }
Example #4
0
        public void SubstitutionsReplaceDifferences()
        {
            //Arrange
            var refGuids = GuidArray(3);
            var table1   = _om.Make <SnapshotObjectMother.GuidKeyTable>(GuidArray(4));

            void TakeSnapshot(string name)
            {
                var builder = _om.NewSnapshot(name);

                table1.ToSnapshotTable(builder);
            }

            TakeSnapshot("Before");
            table1[0].Variable = "edited";
            table1[1].Variable = "edited";
            TakeSnapshot("After");

            var before = _om.GetSnapshot("Before");
            var after  = _om.GetSnapshot("After");

            var allDiffs = SnapshotDifferenceCalculator.GetDifferences(_om.Collection, before, after);
            var diffs    = DifferenceRegulator.ExpandDifferences(_om.Collection, allDiffs, before);

            var tables            = diffs.Select(d => d.TableDefinition).ToList();
            var unpredictableCols = UnpredictableColumnLocator.Locate(tables).Single(t => t.Table.TableName == nameof(SnapshotObjectMother.GuidKeyTable));
            var columnValueSets   = UnpredictableValueScanner.Scan(unpredictableCols, diffs);

            //Act
            var result = ValueSubstituter.Substitute(columnValueSets, diffs, _om.Collection);

            //Assert
            var output = new Output();

            result.Report(output);
            output.Report.Verify();
        }
 internal static DbExpression Substitute(DbExpression original, string referencedVariable, Dictionary<string, DbExpression> propertyValues)
 {
     Debug.Assert(original != null, "Original expression cannot be null");
     ValueSubstituter visitor = new ValueSubstituter(referencedVariable, propertyValues);
     return visitor.VisitExpression(original);
 }
Example #6
0
        private static DbExpression SimplifyNestedTphDiscriminator(DbExpression expression)
        {
            var entityProjection    = (DbProjectExpression)expression;
            var booleanColumnFilter = (DbFilterExpression)entityProjection.Input.Expression;
            var rowProjection       = (DbProjectExpression)booleanColumnFilter.Input.Expression;
            var discriminatorFilter = (DbFilterExpression)rowProjection.Input.Expression;

            var predicates         = FlattenOr(booleanColumnFilter.Predicate).ToList();
            var propertyPredicates =
                predicates.OfType <DbPropertyExpression>()
                .Where(
                    px => px.Instance.ExpressionKind == DbExpressionKind.VariableReference &&
                    ((DbVariableReferenceExpression)px.Instance).VariableName == booleanColumnFilter.Input.VariableName)
                .ToList();

            if (predicates.Count
                != propertyPredicates.Count)
            {
                return(null);
            }

            var predicateColumnNames = propertyPredicates.Select(px => px.Property.Name).ToList();

            var discriminatorPredicates = new Dictionary <object, DbComparisonExpression>();

            if (!TypeSemantics.IsEntityType(discriminatorFilter.Input.VariableType)
                ||
                !TryMatchDiscriminatorPredicate(discriminatorFilter, (compEx, discValue) => discriminatorPredicates.Add(discValue, compEx)))
            {
                return(null);
            }

            var discriminatorProp    = (EdmProperty)((DbPropertyExpression)(discriminatorPredicates.First().Value).Left).Property;
            var rowConstructor       = (DbNewInstanceExpression)rowProjection.Projection;
            var resultRow            = TypeHelpers.GetEdmType <RowType>(rowConstructor.ResultType);
            var inputPredicateMap    = new Dictionary <string, DbComparisonExpression>();
            var selectorPredicateMap = new Dictionary <string, DbComparisonExpression>();
            var columnValues         = new Dictionary <string, DbExpression>(rowConstructor.Arguments.Count);

            for (var idx = 0; idx < rowConstructor.Arguments.Count; idx++)
            {
                var propName  = resultRow.Properties[idx].Name;
                var columnVal = rowConstructor.Arguments[idx];
                if (predicateColumnNames.Contains(propName))
                {
                    if (columnVal.ExpressionKind
                        != DbExpressionKind.Case)
                    {
                        return(null);
                    }
                    var casePredicate = (DbCaseExpression)columnVal;
                    if (casePredicate.When.Count != 1
                        ||
                        !TypeSemantics.IsBooleanType(casePredicate.Then[0].ResultType) ||
                        !TypeSemantics.IsBooleanType(casePredicate.Else.ResultType)
                        ||
                        casePredicate.Then[0].ExpressionKind != DbExpressionKind.Constant ||
                        casePredicate.Else.ExpressionKind != DbExpressionKind.Constant
                        ||
                        (bool)((DbConstantExpression)casePredicate.Then[0]).Value != true ||
                        (bool)((DbConstantExpression)casePredicate.Else).Value)
                    {
                        return(null);
                    }

                    DbPropertyExpression comparedProp;
                    object constValue;
                    if (
                        !TryMatchPropertyEqualsValue(
                            casePredicate.When[0], rowProjection.Input.VariableName, out comparedProp, out constValue)
                        ||
                        comparedProp.Property != discriminatorProp
                        ||
                        !discriminatorPredicates.ContainsKey(constValue))
                    {
                        return(null);
                    }

                    inputPredicateMap.Add(propName, discriminatorPredicates[constValue]);
                    selectorPredicateMap.Add(propName, (DbComparisonExpression)casePredicate.When[0]);
                }
                else
                {
                    columnValues.Add(propName, columnVal);
                }
            }

            // Build a new discriminator-based filter that only includes the same rows allowed by the higher '_from0' column-based filter
            var newDiscriminatorPredicate = Helpers.BuildBalancedTreeInPlace(
                new List <DbExpression>(inputPredicateMap.Values), (left, right) => left.Or(right));

            discriminatorFilter = discriminatorFilter.Input.Filter(newDiscriminatorPredicate);

            var entitySelector = (DbCaseExpression)entityProjection.Projection;
            var newWhens       = new List <DbExpression>(entitySelector.When.Count);
            var newThens       = new List <DbExpression>(entitySelector.Then.Count);

            for (var idx = 0; idx < entitySelector.When.Count; idx++)
            {
                var propWhen   = (DbPropertyExpression)entitySelector.When[idx];
                var entityThen = (DbNewInstanceExpression)entitySelector.Then[idx];

                DbComparisonExpression discriminatorWhen;
                if (!selectorPredicateMap.TryGetValue(propWhen.Property.Name, out discriminatorWhen))
                {
                    return(null);
                }
                newWhens.Add(discriminatorWhen);

                var inputBoundEntityConstructor = ValueSubstituter.Substitute(entityThen, entityProjection.Input.VariableName, columnValues);
                newThens.Add(inputBoundEntityConstructor);
            }

            var newElse           = ValueSubstituter.Substitute(entitySelector.Else, entityProjection.Input.VariableName, columnValues);
            var newEntitySelector = DbExpressionBuilder.Case(newWhens, newThens, newElse);

            DbExpression result = discriminatorFilter.BindAs(rowProjection.Input.VariableName).Project(newEntitySelector);

            return(result);
        }
 internal static DbExpression Substitute(
     DbExpression original, string referencedVariable, Dictionary<string, DbExpression> propertyValues)
 {
     DebugCheck.NotNull(original);
     var visitor = new ValueSubstituter(referencedVariable, propertyValues);
     return visitor.VisitExpression(original);
 }