Welcome to mirror list, hosted at ThFree Co, Russian Federation.

FragmentQuery.cs « QueryRewriting « ViewGeneration « Mapping « Data « System « System.Data.Entity « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 934e2018a15262bdc101338233b020d7b58b667f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//---------------------------------------------------------------------
// <copyright file="FragmentQuery.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Data.Common.Utils;
using System.Data.Common.Utils.Boolean;
using System.Data.Mapping.ViewGeneration.Structures;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Globalization;

namespace System.Data.Mapping.ViewGeneration.QueryRewriting
{
    internal class FragmentQuery : ITileQuery
    {
        private BoolExpression m_fromVariable; // optional
        private string m_label; // optional

        private HashSet<MemberPath> m_attributes;
        private BoolExpression m_condition;

        public HashSet<MemberPath> Attributes
        {
            get { return m_attributes; }
        }

        public BoolExpression Condition
        {
            get { return m_condition; }
        }

        public static FragmentQuery Create(BoolExpression fromVariable, CellQuery cellQuery)
        {
            BoolExpression whereClause = cellQuery.WhereClause;
            whereClause = whereClause.MakeCopy();
            whereClause.ExpensiveSimplify();
            return new FragmentQuery(null /*label*/, fromVariable, new HashSet<MemberPath>(cellQuery.GetProjectedMembers()), whereClause);
        }

        public static FragmentQuery Create(string label, RoleBoolean roleBoolean, CellQuery cellQuery)
        {
            BoolExpression whereClause = cellQuery.WhereClause.Create(roleBoolean);
            whereClause = BoolExpression.CreateAnd(whereClause, cellQuery.WhereClause);
            //return new FragmentQuery(label, null /* fromVariable */, new HashSet<MemberPath>(cellQuery.GetProjectedMembers()), whereClause);
            // don't need any attributes 
            whereClause = whereClause.MakeCopy();
            whereClause.ExpensiveSimplify();
            return new FragmentQuery(label, null /* fromVariable */, new HashSet<MemberPath>(), whereClause);
        }

        public static FragmentQuery Create(IEnumerable<MemberPath> attrs, BoolExpression whereClause)
        {
            return new FragmentQuery(null /* no name */, null /* no fromVariable*/, attrs, whereClause);
        }

        public static FragmentQuery Create(BoolExpression whereClause)
        {
            return new FragmentQuery(null /* no name */, null /* no fromVariable*/, new MemberPath[] { }, whereClause);
        }

        internal FragmentQuery(string label, BoolExpression fromVariable, IEnumerable<MemberPath> attrs, BoolExpression condition)
        {
            m_label = label;
            m_fromVariable = fromVariable;
            m_condition = condition;
            m_attributes = new HashSet<MemberPath>(attrs);
        }

        public BoolExpression FromVariable
        {
            get { return m_fromVariable; }
        }

        public string Description
        {
            get
            {
                string label = m_label;
                if (label == null && m_fromVariable != null)
                {
                    label = m_fromVariable.ToString();
                }
                return label;
            }
        }

        public override string ToString()
        {
            // attributes
            StringBuilder b = new StringBuilder();
            foreach (MemberPath value in this.Attributes)
            {
                if (b.Length > 0) { b.Append(','); }
                b.Append(value.ToString());
            }

            if (Description != null && Description != b.ToString())
            {
                return String.Format(CultureInfo.InvariantCulture, "{0}: [{1} where {2}]", Description, b, this.Condition);
            }
            else
            {
                return String.Format(CultureInfo.InvariantCulture, "[{0} where {1}]", b, this.Condition);
            }
        }

        #region Static methods

        // creates a condition member=value
        internal static BoolExpression CreateMemberCondition(MemberPath path, Constant domainValue, MemberDomainMap domainMap)
        {
            if (domainValue is TypeConstant)
            {
                return BoolExpression.CreateLiteral(new TypeRestriction(new MemberProjectedSlot(path),
                                                    new Domain(domainValue, domainMap.GetDomain(path))), domainMap);
            }
            else
            {
                return BoolExpression.CreateLiteral(new ScalarRestriction(new MemberProjectedSlot(path),
                                                    new Domain(domainValue, domainMap.GetDomain(path))), domainMap);
            }
        }

        internal static IEqualityComparer<FragmentQuery> GetEqualityComparer(FragmentQueryProcessor qp)
        {
            return new FragmentQueryEqualityComparer(qp);
        }

        #endregion

        #region Equality Comparer
        // Two queries are "equal" if they project the same set of attributes
        // and their WHERE clauses are equivalent
        private class FragmentQueryEqualityComparer : IEqualityComparer<FragmentQuery>
        {
            FragmentQueryProcessor _qp;

            internal FragmentQueryEqualityComparer(FragmentQueryProcessor qp)
            {
                _qp = qp;
            }

            #region IEqualityComparer<FragmentQuery> Members

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2140:TransparentMethodsMustNotReferenceCriticalCode", Justification = "Based on Bug VSTS Pioneer #433188: IsVisibleOutsideAssembly is wrong on generic instantiations.")]       
            public bool Equals(FragmentQuery x, FragmentQuery y)
            {
                if (!x.Attributes.SetEquals(y.Attributes))
                {
                    return false;
                }
                return _qp.IsEquivalentTo(x, y);
            }

            // Hashing a bit naive: it exploits syntactic properties,
            // i.e., some semantically equivalent queries may produce different hash codes
            // But that's fine for usage scenarios in QueryRewriter.cs 
            public int GetHashCode(FragmentQuery q)
            {
                int attrHashCode = 0;
                foreach (MemberPath member in q.Attributes)
                {
                    attrHashCode ^= MemberPath.EqualityComparer.GetHashCode(member);
                }
                int varHashCode = 0;
                int constHashCode = 0;
                foreach (MemberRestriction oneOf in q.Condition.MemberRestrictions)
                {
                    varHashCode ^= MemberPath.EqualityComparer.GetHashCode(oneOf.RestrictedMemberSlot.MemberPath);
                    foreach (Constant constant in oneOf.Domain.Values)
                    {
                        constHashCode ^= Constant.EqualityComparer.GetHashCode(constant);
                    }
                }
                return attrHashCode * 13 + varHashCode * 7 + constHashCode;
            }

            #endregion
        }
        #endregion

    }

}