Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
LeftOuterJoinedSource.cs
1using System;
3using System.Threading.Tasks;
9
11{
16 {
24 : base(Left, Right, Conditions)
25 {
26 }
27
31 protected virtual bool Flipped => false;
32
44 public override async Task<IResultSetEnumerator> Find(int Offset, int Top, bool Generic, ScriptNode Where, Variables Variables,
45 KeyValuePair<VariableReference, bool>[] Order, ScriptNode Node)
46 {
47 ScriptNode LeftWhere = await Reduce(this.Left, Where);
48 KeyValuePair<VariableReference, bool>[] LeftOrder = await Reduce(this.Left, Order);
49
50 IResultSetEnumerator e = await this.Left.Find(0, int.MaxValue, Generic, LeftWhere, Variables, LeftOrder, Node);
51
52 ScriptNode RightWhere = this.Combine(await Reduce(this.Right, this.Left, Where), this.Conditions);
53
54 e = new LeftOuterJoinEnumerator(e, this.Left.Name, this.Right, this.Right.Name, Generic, RightWhere, Variables, this.Flipped);
55
56 if (!(Where is null))
57 e = new ConditionalEnumerator(e, Variables, Where);
58
59 if (Offset > 0)
60 e = new OffsetEnumerator(e, Offset);
61
62 if (Top != int.MaxValue)
63 e = new MaxCountEnumerator(e, Top);
64
65 return e;
66 }
67
68 internal class LeftOuterJoinEnumerator : IResultSetEnumerator
69 {
70 private readonly IResultSetEnumerator left;
71 private readonly IDataSource rightSource;
72 private readonly ScriptNode conditions;
73 private readonly Variables variables;
74 private readonly string leftName;
75 private readonly string rightName;
76 private readonly bool hasLeftName;
77 private readonly bool flipped;
78 private readonly bool generic;
79 private bool rightFirst;
80 private IResultSetEnumerator right;
81 private JoinedObject current = null;
82 private GenericObject defaultRight = null;
83 private ObjectProperties leftVariables = null;
84
85 public LeftOuterJoinEnumerator(IResultSetEnumerator Left, string LeftName, IDataSource RightSource, string RightName,
86 bool Generic, ScriptNode Conditions, Variables Variables, bool Flipped)
87 {
88 this.left = Left;
89 this.leftName = LeftName;
90 this.rightName = RightName;
91 this.rightSource = RightSource;
92 this.generic = Generic;
93 this.conditions = Conditions;
94 this.variables = Variables;
95 this.hasLeftName = !string.IsNullOrEmpty(this.leftName);
96 this.flipped = Flipped;
97 }
98
99 public object Current => this.current;
100
101 public void Dispose()
102 {
103 this.left.Dispose();
104 }
105
106 public bool MoveNext()
107 {
108 return this.MoveNextAsync().Result;
109 }
110
111 public async Task<bool> MoveNextAsync()
112 {
113 while (true)
114 {
115 if (!(this.right is null))
116 {
117 bool First = this.rightFirst;
118 this.rightFirst = false;
119
120 if (await this.right.MoveNextAsync())
121 {
122 if (this.flipped)
123 this.current = new JoinedObject(this.right.Current, this.rightName, this.left.Current, this.leftName);
124 else
125 this.current = new JoinedObject(this.left.Current, this.leftName, this.right.Current, this.rightName);
126
127 return true;
128 }
129 else
130 {
131 this.right = null;
132
133 if (First)
134 {
135 if (this.defaultRight is null)
136 {
137 this.defaultRight = new GenericObject(this.rightSource.CollectionName,
138 typeof(GenericObject).FullName, Guid.Empty, Array.Empty<KeyValuePair<string, object>>());
139 }
140
141 if (this.flipped)
142 this.current = new JoinedObject(this.defaultRight, this.rightName, this.left.Current, this.leftName);
143 else
144 this.current = new JoinedObject(this.left.Current, this.leftName, this.defaultRight, this.rightName);
145
146 return true;
147 }
148 }
149 }
150
151 if (!await this.left.MoveNextAsync())
152 return false;
153
154 if (this.leftVariables is null)
155 this.leftVariables = new ObjectProperties(this.left.Current, this.variables);
156 else
157 this.leftVariables.Object = this.left.Current;
158
159 if (this.hasLeftName)
160 this.leftVariables[this.leftName] = this.left.Current;
161
162 this.right = await this.rightSource.Find(0, int.MaxValue, this.generic, this.conditions, this.leftVariables,
163 null, this.conditions);
164
165 this.rightFirst = true;
166 }
167 }
168
169 public void Reset()
170 {
171 this.current = null;
172 this.right = null;
173 this.left.Reset();
174 }
175 }
176
190 public override async Task<bool> Process(IProcessor<object> Processor, int Offset, int Top, bool Generic,
191 ScriptNode Where, Variables Variables, KeyValuePair<VariableReference, bool>[] Order,
192 ScriptNode Node)
193 {
194 ScriptNode LeftWhere = await Reduce(this.Left, Where);
195 KeyValuePair<VariableReference, bool>[] LeftOrder = await Reduce(this.Left, Order);
196
197 ScriptNode RightWhere = await Reduce(this.Right, this.Left, Where);
198 RightWhere = this.Combine(RightWhere, this.Conditions);
199
200 if (Top != int.MaxValue)
201 Processor = new MaxCountProcessor(Processor, Top);
202
203 if (Offset > 0)
204 Processor = new OffsetProcessor(Processor, Offset);
205
206 if (!(Where is null))
207 Processor = new ConditionalProcessor(Processor, Variables, Where);
208
209 Processor = new OuterJoinLeftProcessor(Processor, this.Left.Name, this.Right,
210 this.Right.Name, Generic, RightWhere, Variables, this.Flipped);
211
212 return await this.Left.Process(Processor, 0, int.MaxValue, Generic,
213 LeftWhere, Variables, LeftOrder, Node);
214 }
215
216 internal class OuterJoinLeftProcessor : IProcessor<object>
217 {
218 private readonly OuterJoinRightProcessor rightProcessor;
219 private readonly IDataSource rightSource;
220 private readonly ScriptNode conditions;
221 private readonly Variables variables;
222 private readonly string leftName;
223 private readonly bool hasLeftName;
224 private readonly bool generic;
225 private ObjectProperties leftVariables = null;
226
227 public OuterJoinLeftProcessor(IProcessor<object> Processor, string LeftName,
228 IDataSource RightSource, string RightName, bool Generic,
230 {
231 this.rightProcessor = new OuterJoinRightProcessor(Processor, LeftName,
232 RightSource, RightName, Flipped);
233
234 this.leftName = LeftName;
235 this.rightSource = RightSource;
236 this.generic = Generic;
237 this.conditions = Conditions;
238 this.variables = Variables;
239 this.hasLeftName = !string.IsNullOrEmpty(this.leftName);
240 }
241
242 public bool IsAsynchronous => true;
243 public bool Process(object Object) => this.ProcessAsync(Object).Result;
244 public bool Flush() => this.rightProcessor.Flush();
245 public Task<bool> FlushAsync() => this.rightProcessor.FlushAsync();
246
247 public async Task<bool> ProcessAsync(object Object)
248 {
249 if (this.leftVariables is null)
250 this.leftVariables = new ObjectProperties(Object, this.variables);
251 else
252 this.leftVariables.Object = Object;
253
254 if (this.hasLeftName)
255 this.leftVariables[this.leftName] = Object;
256
257 this.rightProcessor.CurrentLeft = Object;
258
259 return await this.rightSource.Process(this.rightProcessor, 0, int.MaxValue,
260 this.generic, this.conditions, this.leftVariables, null, this.conditions);
261 }
262 }
263
264 private class OuterJoinRightProcessor : IProcessor<object>
265 {
266 private readonly IDataSource rightSource;
267 private readonly IProcessor<object> processor;
268 private readonly string leftName;
269 private readonly string rightName;
270 private readonly bool flipped;
271 private GenericObject defaultRight = null;
272 private object currentLeft = null;
273 private bool firstRight = true;
274
275 public OuterJoinRightProcessor(IProcessor<object> Processor, string LeftName,
276 IDataSource RightSource, string RightName, bool Flipped)
277 {
278 this.processor = Processor;
279 this.leftName = LeftName;
280 this.rightSource = RightSource;
281 this.rightName = RightName;
282 this.flipped = Flipped;
283 }
284
285 public object CurrentLeft
286 {
287 get => this.currentLeft;
288 set
289 {
290 this.currentLeft = value;
291 this.firstRight = true;
292 }
293 }
294
295 public bool IsAsynchronous => this.processor.IsAsynchronous;
296
297 public bool Process(object Object)
298 {
299 this.firstRight = false;
300
301 if (this.flipped)
302 {
303 return this.processor.Process(new JoinedObject(Object, this.rightName,
304 this.CurrentLeft, this.leftName));
305 }
306 else
307 {
308 return this.processor.Process(new JoinedObject(this.CurrentLeft,
309 this.leftName, Object, this.rightName));
310 }
311 }
312
313 public Task<bool> ProcessAsync(object Object)
314 {
315 this.firstRight = false;
316
317 if (this.flipped)
318 {
319 return this.processor.ProcessAsync(new JoinedObject(Object, this.rightName,
320 this.CurrentLeft, this.leftName));
321 }
322 else
323 {
324 return this.processor.ProcessAsync(new JoinedObject(this.CurrentLeft,
325 this.leftName, Object, this.rightName));
326 }
327 }
328
329 public bool Flush()
330 {
331 if (this.firstRight)
332 {
333 if (this.defaultRight is null)
334 {
335 this.defaultRight = new GenericObject(this.rightSource.CollectionName,
336 typeof(GenericObject).FullName, Guid.Empty,
337 Array.Empty<KeyValuePair<string, object>>());
338 }
339
340 this.Process(this.defaultRight);
341 }
342
343 return this.processor.Flush();
344 }
345
346 public async Task<bool> FlushAsync()
347 {
348 if (this.firstRight)
349 {
350 if (this.defaultRight is null)
351 {
352 this.defaultRight = new GenericObject(this.rightSource.CollectionName,
353 typeof(GenericObject).FullName, Guid.Empty,
354 Array.Empty<KeyValuePair<string, object>>());
355 }
356
357 await this.ProcessAsync(this.defaultRight);
358 }
359
360 return await this.processor.FlushAsync();
361 }
362 }
363
364 }
365}
Generic object. Contains a sequence of properties.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
Enumerator that only returns elements matching a set of conditions.
Enumerator that limits the return set to a maximum number of records.
Enumerator that skips a given number of result records.
Processor that only processes elements matching a set of conditions.
Processor that limits the return set to a maximum number of records.
Processor that skips a given number of result records.
Abstract base classes of joined sources.
Definition: JoinedSource.cs:15
ScriptNode Conditions
Conditions for join.
Definition: JoinedSource.cs:46
ScriptNode Combine(ScriptNode Where, ScriptNode On)
Combines one or two restrictions.
static async Task< ScriptNode > Reduce(IDataSource Source, ScriptNode Where)
Reduces a where clause to fit the current data source.
Data source formed through an LEFT [OUTER] JOIN of two sources.
LeftOuterJoinedSource(IDataSource Left, IDataSource Right, ScriptNode Conditions)
Data source formed through an LEFT [OUTER] JOIN of two sources.
override async Task< bool > Process(IProcessor< object > Processor, int Offset, int Top, bool Generic, ScriptNode Where, Variables Variables, KeyValuePair< VariableReference, bool >[] Order, ScriptNode Node)
Processes objects matching filter conditions in Where .
override async Task< IResultSetEnumerator > Find(int Offset, int Top, bool Generic, ScriptNode Where, Variables Variables, KeyValuePair< VariableReference, bool >[] Order, ScriptNode Node)
Finds objects matching filter conditions in Where .
virtual bool Flipped
If sources should be flipped in the JoinedObject instances created.
Collection of variables.
Definition: Variables.cs:25
Task< bool > MoveNextAsync()
Advances the enumerator to the next element of the collection.
Interface for processors of objects.
Definition: IProcessor.cs:9
bool Process(T Object)
Processes an object synchronously.
Task< bool > ProcessAsync(T Object)
Processes an object asynchronously.
Interface for data sources that can be used in SQL statements.
Definition: IDataSource.cs:14
Task< IResultSetEnumerator > Find(int Offset, int Top, bool Generic, ScriptNode Where, Variables Variables, KeyValuePair< VariableReference, bool >[] Order, ScriptNode Node)
Finds objects matching filter conditions in Where .
string Name
Collection name or alias.
Definition: IDataSource.cs:94