/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns>true if the enumerator was successfully advanced to the next element; false if /// the enumerator has passed the end of the collection.</returns> /// <exception cref="InvalidOperationException">The collection was modified after the enumerator was created.</exception> public async Task <bool> MoveNextAsync() { if (!await this.e.MoveNextAsync()) { return(false); } int i; object Item = e.Current; IElement Element = Item as IElement; if (this.properties is null) { this.properties = new ObjectProperties(Element?.AssociatedObjectValue ?? Item, this.variables); } else { this.properties.Object = Element?.AssociatedObjectValue ?? Item; } if (this.columns is null) { this.record = new IElement[1] { Element ?? Expression.Encapsulate(Item) } } ; else { this.record = new IElement[this.count]; for (i = 0; i < this.count; i++) { try { this.record[i] = this.columns[i].Evaluate(this.properties); } catch (Exception ex) { ex = Log.UnnestException(ex); this.record[i] = Expression.Encapsulate(ex); } } } return(true); }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns>true if the enumerator was successfully advanced to the next element; false if /// the enumerator has passed the end of the collection.</returns> /// <exception cref="InvalidOperationException">The collection was modified after the enumerator was created.</exception> public async Task <bool> MoveNextAsync() { if (!await this.e.MoveNextAsync()) { return(false); } this.current = this.e.Current; if (this.objectVariables is null) { this.objectVariables = new ObjectProperties(this.current, this.variables); } else { this.objectVariables.Object = e.Current; } if (this.current is GenericObject GenObj) { foreach (KeyValuePair <string, ScriptNode> P in this.additionalFields) { GenObj[P.Key] = P.Value.Evaluate(this.objectVariables); } } else if (this.current is GroupObject GroupObj) { foreach (KeyValuePair <string, ScriptNode> P in this.additionalFields) { GroupObj[P.Key] = P.Value.Evaluate(this.objectVariables); } } else { GroupObject Obj = new GroupObject(new object[] { this.current }, new object[0], new ScriptNode[0], this.objectVariables); foreach (KeyValuePair <string, ScriptNode> P in this.additionalFields) { Obj[P.Key] = P.Value.Evaluate(this.objectVariables); } this.current = Obj; } return(true); }
private bool MatchesCondition() { try { ObjectProperties Properties = new ObjectProperties(this.e.Current, this.variables); IElement E = this.conditions.Evaluate(Properties); if (!(E is BooleanValue B) || !B.Value) { return(false); } return(true); } catch (Exception) { return(false); } }
/// <summary> /// <see cref="IEnumerator.MoveNext"/> /// </summary> public bool MoveNext() { while (e.MoveNext()) { try { ObjectProperties Properties = new ObjectProperties(e.Current, this.variables); IElement E = this.conditions.Evaluate(Properties); if (!(E is BooleanValue B) || !B.Value) { continue; } return(true); } catch (Exception) { continue; } } return(false); }
/// <summary> /// Evaluates the node, using the variables provided in the <paramref name="Variables"/> collection. /// </summary> /// <param name="Variables">Variables collection.</param> /// <returns>Result.</returns> public override IElement Evaluate(Variables Variables) { IElement E; int Top; int Offset; int i, c; if (this.top != null) { E = this.top.Evaluate(Variables); Top = (int)Expression.ToDouble(E.AssociatedObjectValue); if (Top <= 0) { throw new ScriptRuntimeException("TOP must evaluate to a positive integer.", this.top); } } else { Top = int.MaxValue; } if (this.offset != null) { E = this.offset.Evaluate(Variables); Offset = (int)Expression.ToDouble(E.AssociatedObjectValue); if (Offset < 0) { throw new ScriptRuntimeException("OFFSET must evaluate to a non-negative integer.", this.offset); } } else { Offset = 0; } c = this.sources.Length; if (c != 1) { throw new ScriptRuntimeException("Joinds between multiple sources not supported.", this); } E = this.sources[0].Evaluate(Variables); if (!(E.AssociatedObjectValue is Type T)) { throw new ScriptRuntimeException("Type expected.", this.sources[0]); } List <string> OrderBy = new List <string>(); bool CalculatedOrder = false; if (this.orderBy != null) { foreach (KeyValuePair <ScriptNode, bool> Node in this.orderBy) { if (Node.Key is VariableReference Ref) { if (Node.Value) { OrderBy.Add(Ref.VariableName); } else { OrderBy.Add("-" + Ref.VariableName); } } else { CalculatedOrder = true; } } } if (this.groupBy != null) { foreach (ScriptNode Node in this.groupBy) { if (Node is VariableReference Ref) { if (!OrderBy.Contains(Ref.VariableName)) { OrderBy.Add(Ref.VariableName); } } else { CalculatedOrder = true; } } } bool ManualPaging = this.groupBy != null || this.where != null; bool ManualTop = Top != int.MaxValue && ManualPaging; bool ManualOffset = Offset != 0 && ManualPaging; IEnumerator e = Find(T, ManualOffset ? 0 : Offset, ManualTop ? int.MaxValue : Top, this.where, Variables, OrderBy.ToArray(), this); LinkedList <IElement[]> Items = new LinkedList <IElement[]>(); Dictionary <string, int> Columns = new Dictionary <string, int>(); IElement[] Rec; int NrRecords = 0; if (this.columns != null) { c = this.columns.Length; for (i = 0; i < c; i++) { if (this.columns[i] is VariableReference Ref) { Columns[Ref.VariableName] = i; } } } else { c = 0; } if (this.where != null) { e = new ConditionalEnumerator(e, Variables, this.where); } if (this.groupBy != null) { e = new GroupEnumerator(e, Variables, this.groupBy, this.groupByNames); if (this.having != null) { e = new ConditionalEnumerator(e, Variables, this.having); } } if (CalculatedOrder) { List <KeyValuePair <ScriptNode, bool> > Order = new List <KeyValuePair <ScriptNode, bool> >(); if (this.orderBy != null) { Order.AddRange(this.orderBy); } if (this.groupByNames != null) { foreach (ScriptNode Group in this.groupByNames) { if (Group != null) { Order.Add(new KeyValuePair <ScriptNode, bool>(Group, true)); } } } e = new CustomOrderEnumerator(e, Variables, Order.ToArray()); } while (e.MoveNext()) { if (ManualOffset && Offset > 0) { Offset--; continue; } object Item = e.Current; ObjectProperties Properties = new ObjectProperties(Item, Variables); if (this.columns is null) { Rec = new IElement[1] { Expression.Encapsulate(Item) } } ; else { Rec = new IElement[c]; for (i = 0; i < c; i++) { try { Rec[i] = this.columns[i].Evaluate(Properties); } catch (Exception ex) { ex = Log.UnnestException(ex); Rec[i] = Expression.Encapsulate(ex); } } } Items.AddLast(Rec); NrRecords++; if (ManualTop && NrRecords >= Top) { break; } } IElement[] Elements = new IElement[this.columns is null ? NrRecords : NrRecords * c];
/// <summary> /// Enumerator that reorders a sequence of items. /// </summary> /// <param name="ItemEnumerator">Item enumerator</param> /// <param name="Variables">Current set of variables.</param> /// <param name="Order">Custom order.</param> public CustomOrderEnumerator(IEnumerator ItemEnumerator, Variables Variables, KeyValuePair <ScriptNode, bool>[] Order) { this.variables = Variables; this.order = Order; List <object> Items = new List <object>(); while (ItemEnumerator.MoveNext()) { Items.Add(ItemEnumerator.Current); } Dictionary <Type, ObjectProperties> PropertiesX = new Dictionary <Type, ObjectProperties>(); Dictionary <Type, ObjectProperties> PropertiesY = new Dictionary <Type, ObjectProperties>(); Items.Sort((x, y) => { if (x is null) { if (y is null) { return(0); } else { return(-1); } } else if (y is null) { return(1); } Type Tx = x.GetType(); Type Ty = y.GetType(); if (PropertiesX.TryGetValue(Tx, out ObjectProperties Vx)) { Vx.Object = x; } else { Vx = new ObjectProperties(x, Variables); PropertiesX[Tx] = Vx; } if (PropertiesY.TryGetValue(Ty, out ObjectProperties Vy)) { Vy.Object = y; } else { Vy = new ObjectProperties(y, Variables); PropertiesY[Ty] = Vy; } int i, j, c = this.order.Length; IElement Ex, Ey; ScriptNode Node; for (i = 0; i < c; i++) { Node = this.order[i].Key; Ex = Node.Evaluate(Vx); Ey = Node.Evaluate(Vy); if (!(Ex.AssociatedSet is IOrderedSet S)) { throw new ScriptRuntimeException("Result not member of an ordered set.", Node); } j = S.Compare(Ex, Ey); if (j != 0) { if (this.order[i].Value) { return(j); } else { return(-j); } } } return(0); }); this.e = Items.GetEnumerator(); }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns>true if the enumerator was successfully advanced to the next element; false if /// the enumerator has passed the end of the collection.</returns> /// <exception cref="InvalidOperationException">The collection was modified after the enumerator was created.</exception> public async Task <bool> MoveNextAsync() { Dictionary <string, List <object> > Aggregated = null; ObjectProperties Variables = null; IElement E; object[] Last = null; int i, c = this.groupBy.Length; object o1, o2; while (this.processLast || await e.MoveNextAsync()) { this.processLast = false; Variables = new ObjectProperties(e.Current, this.variables); if (Last is null) { Last = new object[c]; for (i = 0; i < c; i++) { E = this.groupBy[i].Evaluate(Variables); Last[i] = E.AssociatedObjectValue; } } else { for (i = 0; i < c; i++) { E = this.groupBy[i].Evaluate(Variables); o1 = Last[i]; o2 = E.AssociatedObjectValue; if (o1 is null ^ o2 is null) { break; } if (o1 != null && !o1.Equals(o2)) { break; } } if (i < c) { this.processLast = true; break; } } o1 = e.Current; Type T = o1.GetType(); if (T != this.lastType) { this.lastType = T; this.properties = T.GetRuntimeProperties(); this.fields = T.GetRuntimeFields(); } if (Aggregated is null) { Aggregated = new Dictionary <string, List <object> >(); } foreach (PropertyInfo PI in this.properties) { if (!PI.CanRead || !PI.CanWrite) { continue; } if (!Aggregated.TryGetValue(PI.Name, out List <object> List)) { List = new List <object>(); Aggregated[PI.Name] = List; } List.Add(PI.GetValue(o1)); } foreach (FieldInfo FI in this.fields) { if (!Aggregated.TryGetValue(FI.Name, out List <object> List)) { List = new List <object>(); Aggregated[FI.Name] = List; } List.Add(FI.GetValue(o1)); } } if (Aggregated is null) { return(false); } Dictionary <string, object> Result = new Dictionary <string, object>(); bool First = true; foreach (KeyValuePair <string, List <object> > Rec in Aggregated) { object[] A = Rec.Value.ToArray(); Result[Rec.Key] = A; if (First) { First = false; Result[" First "] = A; } } if (this.groupNames != null) { for (i = 0; i < c; i++) { ScriptNode Node = this.groupNames[i]; if (Node is null) { continue; } if (Node is VariableReference Ref) { Result[Ref.VariableName] = Last[i]; } else { E = this.groupNames[i]?.Evaluate(Variables); if (E != null && E is StringValue S) { Result[S.Value] = Last[i]; } } } } this.current = Result; return(true); }
/// <summary> /// <see cref="IEnumerator.MoveNext"/> /// </summary> public async Task <bool> MoveNextAsync() { if (this.e is null) { List <object> Items = new List <object>(); while (await this.items.MoveNextAsync()) { Items.Add(this.items.Current); } Items.Sort((x, y) => { if (x is null) { if (y is null) { return(0); } else { return(-1); } } else if (y is null) { return(1); } Type Tx = x.GetType(); Type Ty = y.GetType(); if (this.propertiesX.TryGetValue(Tx, out ObjectProperties Vx)) { Vx.Object = x; } else { Vx = new ObjectProperties(x, this.variables); this.propertiesX[Tx] = Vx; } if (this.propertiesY.TryGetValue(Ty, out ObjectProperties Vy)) { Vy.Object = y; } else { Vy = new ObjectProperties(y, this.variables); this.propertiesY[Ty] = Vy; } int i, j, c = this.order.Length; IElement Ex, Ey; ScriptNode Node; for (i = 0; i < c; i++) { Node = this.order[i].Key; Ex = Node.Evaluate(Vx); Ey = Node.Evaluate(Vy); if (!(Ex.AssociatedSet is IOrderedSet S)) { throw new ScriptRuntimeException("Result not member of an ordered set.", Node); } j = S.Compare(Ex, Ey); if (j != 0) { if (this.order[i].Value) { return(j); } else { return(-j); } } } return(0); }); this.e = Items.GetEnumerator(); } return(this.e.MoveNext()); }