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

Tile.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: 8d490f590c43cffede96f4cddc6c57fbd29d184b (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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
//---------------------------------------------------------------------
// <copyright file="Tile.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.Collections.ObjectModel;
using System.Linq;
using System.Globalization;

namespace System.Data.Mapping.ViewGeneration.QueryRewriting
{
    internal enum TileOpKind
    {
        Union,
        Join,
        AntiSemiJoin,
        // Project,
        Named
    }

    internal interface ITileQuery
    {
        string Description { get; }
    }

    internal abstract class TileQueryProcessor<T_Query> where T_Query : ITileQuery
    {
        internal abstract T_Query Intersect(T_Query arg1, T_Query arg2);
        internal abstract T_Query Difference(T_Query arg1, T_Query arg2);
        internal abstract T_Query Union(T_Query arg1, T_Query arg2);
        internal abstract bool IsSatisfiable(T_Query query);
        internal abstract T_Query CreateDerivedViewBySelectingConstantAttributes(T_Query query);
    }

    internal class DefaultTileProcessor<T_Query> : TileProcessor<Tile<T_Query>> where T_Query : ITileQuery
    {
        private readonly TileQueryProcessor<T_Query> _tileQueryProcessor;

        internal DefaultTileProcessor(TileQueryProcessor<T_Query> tileQueryProcessor)
        {
            _tileQueryProcessor = tileQueryProcessor;
        }

        internal TileQueryProcessor<T_Query> QueryProcessor
        {
            get { return _tileQueryProcessor; }
        }

        internal override bool IsEmpty(Tile<T_Query> tile)
        {
            return false == _tileQueryProcessor.IsSatisfiable(tile.Query);
        }

        internal override Tile<T_Query> Union(Tile<T_Query> arg1, Tile<T_Query> arg2)
        {
            return new TileBinaryOperator<T_Query>(arg1, arg2, TileOpKind.Union, _tileQueryProcessor.Union(arg1.Query, arg2.Query));
        }

        internal override Tile<T_Query> Join(Tile<T_Query> arg1, Tile<T_Query> arg2)
        {
            return new TileBinaryOperator<T_Query>(arg1, arg2, TileOpKind.Join, _tileQueryProcessor.Intersect(arg1.Query, arg2.Query));
        }

        internal override Tile<T_Query> AntiSemiJoin(Tile<T_Query> arg1, Tile<T_Query> arg2)
        {
            return new TileBinaryOperator<T_Query>(arg1, arg2, TileOpKind.AntiSemiJoin, _tileQueryProcessor.Difference(arg1.Query, arg2.Query));
        }

        internal override Tile<T_Query> GetArg1(Tile<T_Query> tile)
        {
            return tile.Arg1;
        }

        internal override Tile<T_Query> GetArg2(Tile<T_Query> tile)
        {
            return tile.Arg2;
        }

        internal override TileOpKind GetOpKind(Tile<T_Query> tile)
        {
            return tile.OpKind;
        }

        internal bool IsContainedIn(Tile<T_Query> arg1, Tile<T_Query> arg2)
        {
            return IsEmpty(AntiSemiJoin(arg1, arg2));
        }

        internal bool IsEquivalentTo(Tile<T_Query> arg1, Tile<T_Query> arg2)
        {
            return IsContainedIn(arg1, arg2) && IsContainedIn(arg2, arg1);
        }
    }

    internal abstract class Tile<T_Query> where T_Query : ITileQuery
    {
        private readonly T_Query m_query;
        private readonly TileOpKind m_opKind;

        protected Tile(TileOpKind opKind, T_Query query)
        {
            m_opKind = opKind;
            m_query = query;
        }

        public T_Query Query
        {
            get { return m_query; }
        }

        public abstract string Description { get; }

        // multiple occurrences possible
        public IEnumerable<T_Query> GetNamedQueries()
        {
            return GetNamedQueries(this);
        }
        private static IEnumerable<T_Query> GetNamedQueries(Tile<T_Query> rewriting)
        {
            if (rewriting != null)
            {
                if (rewriting.OpKind == TileOpKind.Named)
                {
                    yield return ((TileNamed<T_Query>)rewriting).NamedQuery;
                }
                else
                {
                    foreach (T_Query query in GetNamedQueries(rewriting.Arg1))
                    {
                        yield return query;
                    }
                    foreach (T_Query query in GetNamedQueries(rewriting.Arg2))
                    {
                        yield return query;
                    }
                }
            }
        }

        public override string ToString()
        {
            string formattedQuery = this.Description;
            if (formattedQuery != null)
            {
                return String.Format(CultureInfo.InvariantCulture, "{0}: [{1}]", this.Description, this.Query);
            }
            else
            {
                return String.Format(CultureInfo.InvariantCulture, "[{0}]", this.Query);
            }
        }

        public abstract Tile<T_Query> Arg1
        {
            get;
        }

        public abstract Tile<T_Query> Arg2
        {
            get;
        }

        public TileOpKind OpKind
        {
            get { return m_opKind; }
        }

        internal abstract Tile<T_Query> Replace(Tile<T_Query> oldTile, Tile<T_Query> newTile);
    }

    internal class TileNamed<T_Query> : Tile<T_Query> where T_Query : ITileQuery
    {
        public TileNamed(T_Query namedQuery)
            : base(TileOpKind.Named, namedQuery)
        {
            Debug.Assert(namedQuery != null);
        }

        public T_Query NamedQuery
        {
            get { return this.Query; }
        }

        public override Tile<T_Query> Arg1 { get { return null; } }
        public override Tile<T_Query> Arg2 { get { return null; } }

        public override string Description
        {
            get { return this.Query.Description; }
        }

        public override string ToString()
        {
            return this.Query.ToString();
        }

        internal override Tile<T_Query> Replace(Tile<T_Query> oldTile, Tile<T_Query> newTile)
        {
            return (this == oldTile) ? newTile : this;
        }
    }

    internal class TileBinaryOperator<T_Query> : Tile<T_Query> where T_Query : ITileQuery
    {
        private readonly Tile<T_Query> m_arg1;
        private readonly Tile<T_Query> m_arg2;

        public TileBinaryOperator(Tile<T_Query> arg1, Tile<T_Query> arg2, TileOpKind opKind, T_Query query)
            : base(opKind, query)
        {
            Debug.Assert(arg1 != null && arg2 != null);
            m_arg1 = arg1;
            m_arg2 = arg2;
        }

        public override Tile<T_Query> Arg1 { get { return m_arg1; } }
        public override Tile<T_Query> Arg2 { get { return m_arg2; } }

        public override string Description
        {
            get
            {
                string descriptionFormat = null;
                switch (OpKind)
                {
                    case TileOpKind.Join: descriptionFormat = "({0} & {1})"; break;
                    case TileOpKind.AntiSemiJoin: descriptionFormat = "({0} - {1})"; break;
                    case TileOpKind.Union: descriptionFormat = "({0} | {1})"; break;
                    default: Debug.Fail("Unexpected binary operator"); break;
                }
                return String.Format(CultureInfo.InvariantCulture, descriptionFormat, this.Arg1.Description, this.Arg2.Description);
            }
        }

        internal override Tile<T_Query> Replace(Tile<T_Query> oldTile, Tile<T_Query> newTile)
        {
            Tile<T_Query> newArg1 = Arg1.Replace(oldTile, newTile);
            Tile<T_Query> newArg2 = Arg2.Replace(oldTile, newTile);
            if (newArg1 != Arg1 || newArg2 != Arg2)
            {
                return new TileBinaryOperator<T_Query>(newArg1, newArg2, OpKind, Query);
            }
            return this;
        }
    }
}