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