Пример #1
0
        /// <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];
Пример #2
0
        /// <summary>
        /// Evaluates the node asynchronously, using the variables provided in
        /// the <paramref name="Variables"/> collection.
        /// </summary>
        /// <param name="Variables">Variables collection.</param>
        /// <returns>Result.</returns>
        public async Task <IElement> EvaluateAsync(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;
            }

            IDataSource Source = this.source.GetSource(Variables);

            List <KeyValuePair <VariableReference, bool> > OrderBy = new List <KeyValuePair <VariableReference, bool> >();
            bool CalculatedOrder = false;

            if (this.orderBy != null)
            {
                foreach (KeyValuePair <ScriptNode, bool> Node in this.orderBy)
                {
                    if (Node.Key is VariableReference Ref)
                    {
                        OrderBy.Add(new KeyValuePair <VariableReference, bool>(Ref, Node.Value));
                    }
                    else
                    {
                        CalculatedOrder = true;
                        break;
                    }
                }
            }

            if (this.groupBy != null && !CalculatedOrder)
            {
                foreach (ScriptNode Node in this.groupBy)
                {
                    if (Node is VariableReference Ref)
                    {
                        bool Found = false;

                        foreach (KeyValuePair <VariableReference, bool> P in OrderBy)
                        {
                            if (P.Key.VariableName == Ref.VariableName)
                            {
                                Found = true;
                                break;
                            }
                        }

                        if (!Found)
                        {
                            OrderBy.Add(new KeyValuePair <VariableReference, bool>(Ref, true));
                        }
                    }
                    else
                    {
                        CalculatedOrder = true;
                        break;
                    }
                }
            }

            LinkedList <IElement[]>  Items   = new LinkedList <IElement[]>();
            Dictionary <string, int> Columns = new Dictionary <string, int>();
            IResultSetEnumerator     e;
            RecordEnumerator         e2;
            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.groupBy is null)
            {
                e = await Source.Find(Offset, Top, this.where, Variables, OrderBy.ToArray(), this);

                Offset = 0;
                Top    = int.MaxValue;
            }
            else
            {
                e = await Source.Find(0, int.MaxValue, this.where, Variables, OrderBy.ToArray(), this);
            }

            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());
            }

            if (Offset > 0)
            {
                e = new OffsetEnumerator(e, Offset);
            }

            if (Top != int.MaxValue)
            {
                e = new MaxCountEnumerator(e, Top);
            }

            if (this.distinct)
            {
                e2 = new DistinctEnumerator(e, this.columns, Variables);
            }
            else
            {
                e2 = new RecordEnumerator(e, this.columns, Variables);
            }

            while (await e2.MoveNextAsync())
            {
                Items.AddLast(e2.CurrentRecord);
                NrRecords++;
            }

            IElement[] Elements = new IElement[this.columns is null ? NrRecords : NrRecords * c];