예제 #1
0
        public override ISqlValue Divide(ISqlValue a, ISqlValue b)
        {
            if (!(a is SqlNumber) ||
                !(b is SqlNumber))
            {
                return(SqlNull.Value);
            }

            var x = (SqlNumber)a;
            var y = (SqlNumber)b;

            return(SqlMath.Divide(x, y, Precision));
        }
예제 #2
0
        public override ISqlValue Modulo(ISqlValue a, ISqlValue b)
        {
            if (!(a is SqlNumber) ||
                !(b is SqlNumber))
            {
                return(SqlNull.Value);
            }

            var x = (SqlNumber)a;
            var y = (SqlNumber)b;

            return(SqlMath.Remainder(x, y));
        }
예제 #3
0
        public override ISqlValue Multiply(ISqlValue a, ISqlValue b)
        {
            if (!(a is SqlNumber) ||
                !(b is SqlNumber))
            {
                return(SqlNull.Value);
            }

            var x = (SqlNumber)a;
            var y = (SqlNumber)b;

            return(SqlMath.Multiply(x, y));
        }
예제 #4
0
        private void RegisterAggregates()
        {
            // COUNT(*)
            RegisterAggregate("COUNT", Deterministic("column"), PrimitiveTypes.VarNumeric(),
                              iterate => {
                if (iterate.IsFirst)
                {
                    iterate.SetResult(SqlObject.BigInt(1));
                }
                else
                {
                    iterate.SetResult(iterate.Accumulation.Add(SqlObject.BigInt(1)));
                }
            },
                              initialize => {
                var groupResolver = initialize.GetGroupResolver();
                var groupSize     = groupResolver.Size;

                var argRef = (initialize.Input as SqlReferenceExpression)?.ReferenceName;
                if (groupSize == 0 || (argRef != null && argRef.IsGlob))
                {
                    initialize.SetResult(SqlExpression.Constant(SqlObject.BigInt(groupSize)), false);
                }

                return(Task.CompletedTask);
            });

            // MIN
            RegisterAggregate("MIN", Deterministic("column"), PrimitiveTypes.VarNumeric(),
                              iterate => {
                if (iterate.IsFirst)
                {
                    iterate.SetResult(iterate.Current);
                }
                else if (iterate.Current.LessThan(iterate.Accumulation).IsTrue)
                {
                    iterate.SetResult(iterate.Current);
                }
            });

            // MAX
            RegisterAggregate("MAX", Deterministic("column"), PrimitiveTypes.VarNumeric(),
                              iterate => {
                if (iterate.IsFirst)
                {
                    iterate.SetResult(iterate.Current);
                }
                else if (iterate.Current.GreaterThan(iterate.Accumulation).IsTrue)
                {
                    iterate.SetResult(iterate.Current);
                }
                else if (iterate.Accumulation.LessThan(iterate.Current).IsTrue)
                {
                    iterate.SetResult(iterate.Accumulation);
                }
            });

            // AVG
            RegisterAggregate("AVG", Deterministic("column"), PrimitiveTypes.VarNumeric(),
                              iterate => {
                if (iterate.IsFirst)
                {
                    iterate.SetResult(iterate.Current);
                }
                else
                {
                    iterate.SetResult(iterate.Current.Add(iterate.Accumulation));
                }
            }, merge: merge => {
                var groupResolver = merge.GetGroupResolver();
                var groupSize     = groupResolver.Size;

                var final = merge.Accumulated.Divide(SqlObject.BigInt(groupSize));
                merge.SetOutput(final);
                return(Task.CompletedTask);
            });

            // STDEV
            RegisterAggregate("STDEV", Deterministic("column"), PrimitiveTypes.VarNumeric(), iterate => {
                var aggregator = (AvgAggregator)iterate.MethodContext.Metadata["aggregator"];
                aggregator.Values.Add(iterate.Current);

                if (iterate.IsFirst)
                {
                    iterate.SetResult(iterate.Current);
                }
                else
                {
                    iterate.SetResult(iterate.Current.Add(iterate.Accumulation));
                }
            }, initialize => {
                var groupResolver = initialize.GetGroupResolver();
                var aggregator    = new AvgAggregator {
                    Values = new BigList <SqlObject>(groupResolver.Size)
                };

                initialize.MethodContext.Metadata["aggregator"] = aggregator;
                return(Task.CompletedTask);
            }, merge => {
                var groupResolver = merge.GetGroupResolver();
                var groupSize     = groupResolver.Size;
                var aggregator    = (AvgAggregator)merge.MethodContext.Metadata["aggregator"];

                var avg  = merge.Accumulated.Divide(SqlObject.BigInt(groupSize));
                var sums = aggregator.Values.Select(x => SqlMath.Pow((SqlNumber)x.Subtract(avg).Value, (SqlNumber)2));
                var sum  = SqlNumber.Zero;
                foreach (var number in sums)
                {
                    sum += number;
                }

                var ret = SqlMath.Sqrt(sum / (SqlNumber)(groupSize - 1));
                merge.SetOutput(SqlObject.Numeric(ret));
                return(Task.CompletedTask);
            });

            // SUM
            RegisterAggregate("SUM", Deterministic("column"), PrimitiveTypes.VarNumeric(),
                              iterate => {
                if (iterate.IsFirst)
                {
                    iterate.SetResult(iterate.Current);
                }
                else
                {
                    iterate.SetResult(iterate.Current.Add(iterate.Accumulation));
                }
            });

            // LAST
            RegisterAggregate("LAST", Deterministic("column"), new SqlDeterministicType(),
                              iterate => {
                var groupResolver = iterate.GetGroupResolver();
                var groupSize     = groupResolver.Size;

                if (iterate.Offset == groupSize - 1)
                {
                    iterate.SetResult(iterate.Current);
                }
                else
                {
                    iterate.SetResult(SqlObject.Null);
                }
            });

            // FIRST
            RegisterAggregate("FIRST", Deterministic("column"), new SqlDeterministicType(),
                              iterate => {
                if (iterate.IsFirst)
                {
                    iterate.SetResult(iterate.Current, false);
                }
            });

            RegisterAggregate("GROUP_ID", PrimitiveTypes.Integer(),
                              iterate => {
                // no-op
            }, merge: merge => {
                var groupResolver = merge.GetGroupResolver();
                merge.SetOutput(SqlObject.Integer(groupResolver.GroupId));
                return(Task.CompletedTask);
            });
        }