AggregateNode.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / Filter / AggregateNode.cs / 1305376 / AggregateNode.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
 
namespace System.Data {
    using System; 
    using System.Diagnostics;
    using System.Collections.Generic;
    using System.ComponentModel;
 
    internal enum Aggregate {
        None = FunctionId.none, 
        Sum = FunctionId.Sum, 
        Avg = FunctionId.Avg,
        Min = FunctionId.Min, 
        Max = FunctionId.Max,
        Count = FunctionId.Count,
        StDev = FunctionId.StDev,   // Statistical standard deviation
        Var = FunctionId.Var,       // Statistical variance 
    }
 
    internal sealed class AggregateNode : ExpressionNode { 
        private readonly AggregateType type;
        private readonly Aggregate aggregate; 
        private readonly bool local;     // set to true if the aggregate calculated localy (for the current table)

        private readonly string relationName;
        private readonly string columnName; 

        // 
 
        private DataTable childTable;
        private DataColumn column; 
        private DataRelation relation;

        internal AggregateNode(DataTable table, FunctionId aggregateType, string columnName) :
            this(table, aggregateType, columnName, true, null) { 
        }
 
        internal AggregateNode(DataTable table, FunctionId aggregateType, string columnName, string relationName) : 
            this(table, aggregateType, columnName, false, relationName) {
        } 

        internal AggregateNode(DataTable table, FunctionId aggregateType, string columnName, bool local, string relationName) : base(table) {
            Debug.Assert(columnName != null, "Invalid parameter column name (null).");
            this.aggregate = (Aggregate)(int)aggregateType; 

            if (aggregateType == FunctionId.Sum) 
                this.type = AggregateType.Sum; 
            else if (aggregateType == FunctionId.Avg)
                this.type = AggregateType.Mean; 
            else if (aggregateType == FunctionId.Min)
                this.type = AggregateType.Min;
            else if (aggregateType == FunctionId.Max)
                this.type = AggregateType.Max; 
            else if (aggregateType == FunctionId.Count)
                this.type = AggregateType.Count; 
            else if (aggregateType == FunctionId.Var) 
                this.type = AggregateType.Var;
            else if (aggregateType == FunctionId.StDev) 
                this.type = AggregateType.StDev;
            else {
                throw ExprException.UndefinedFunction(Function.FunctionName[(Int32)aggregateType]);
            } 

            this.local = local; 
            this.relationName = relationName; 
            this.columnName = columnName;
        } 
        internal override void Bind(DataTable table, List list) {
            BindTable(table);
            if (table == null)
                throw ExprException.AggregateUnbound(this.ToString()); 

            if (local) { 
                relation = null; 
            }
            else { 
                DataRelationCollection relations;
                relations = table.ChildRelations;

                if (relationName == null) { 
                    // must have one and only one relation
 
                    if (relations.Count > 1) { 
                        throw ExprException.UnresolvedRelation(table.TableName, this.ToString());
                    } 
                    if (relations.Count == 1) {
                        relation = relations[0];
                    }
                    else { 
                        throw ExprException.AggregateUnbound(this.ToString());
                    } 
                } 
                else {
                    relation = relations[relationName]; 
                }
            }

            childTable = (relation == null) ? table : relation.ChildTable; 

            this.column = childTable.Columns[columnName]; 
 
            if (column == null)
                throw ExprException.UnboundName(columnName); 

            // add column to the dependency list, do not add duplicate columns

            Debug.Assert(column != null, "Failed to bind column " + columnName); 

            int i; 
            for (i = 0; i < list.Count; i++) { 
                // walk the list, check if the current column already on the list
                DataColumn dataColumn = (DataColumn)list[i]; 
                if (column == dataColumn) {
                    break;
                }
            } 
            if (i >= list.Count) {
                list.Add(column); 
            } 

            // SQLBU 383715: Staleness of computed values in expression column as the relationship end columns are not being added to the dependent column list. 
            AggregateNode.Bind(relation, list);
        }

        internal static void Bind(DataRelation relation, List list) 
        {
            if (null != relation) { 
                // add the ends of the relationship the expression depends on 
                foreach (DataColumn c in relation.ChildColumnsReference) {
                    if (!list.Contains(c)) { 
                        list.Add(c);
                    }
                }
                foreach (DataColumn c in relation.ParentColumnsReference) { 
                    if (!list.Contains(c)) {
                        list.Add(c); 
                    } 
                }
            } 
        }

        internal override object Eval() {
            return Eval(null, DataRowVersion.Default); 
        }
 
        internal override object Eval(DataRow row, DataRowVersion version) { 
            if (childTable == null)
                throw ExprException.AggregateUnbound(this.ToString()); 

            DataRow[] rows;

            if (local) { 
                rows = new DataRow[childTable.Rows.Count];
                childTable.Rows.CopyTo(rows, 0); 
            } 
            else {
                if (row == null) { 
                    throw ExprException.EvalNoContext();
                }
                if (relation == null) {
                    throw ExprException.AggregateUnbound(this.ToString()); 
                }
                rows = row.GetChildRows(relation, version); 
            } 

            int[] records; 
            if (version == DataRowVersion.Proposed) {
                version = DataRowVersion.Default;
            }
 
            List recordList = new List();
 
            for (int i = 0; i < rows.Length; i++) { 
                if (rows[i].RowState == DataRowState.Deleted) {
                    if (DataRowAction.Rollback != rows[i]._action) { 
                        continue;
                    }
                    Debug.Assert(DataRowVersion.Original == version, "wrong version");
                    version = DataRowVersion.Original; 
                }
                else if ((DataRowAction.Rollback == rows[i]._action) && (rows[i].RowState == DataRowState.Added)) { 
                    continue; // WebData 91297 
                }
                if (version == DataRowVersion.Original && rows[i].oldRecord == -1) { 
                    continue;
                }
                recordList.Add(rows[i].GetRecordFromVersion(version));
            } 
            records = recordList.ToArray();
 
            return column.GetAggregateValue(records, type); 
        }
 
        // Helper for the DataTable.Compute method
        internal override object Eval(int[] records) {
            if (childTable == null)
                throw ExprException.AggregateUnbound(this.ToString()); 
            if (!local) {
                throw ExprException.ComputeNotAggregate(this.ToString()); 
            } 
            return column.GetAggregateValue(records, type);
        } 

        internal override bool IsConstant() {
            return false;
        } 

        internal override bool IsTableConstant() { 
            return local; 
        }
 
        internal override bool HasLocalAggregate() {
            return local;
        }
 
        internal override bool HasRemoteAggregate() {
            return !local; 
        } 

        internal override bool DependsOn(DataColumn column) { 
            if (this.column == column) {
                return true;
            }
            if (this.column.Computed) { 
                return this.column.DataExpression.DependsOn(column);
            } 
            return false; 
        }
 
        internal override ExpressionNode Optimize() {
            return this;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
 
namespace System.Data {
    using System; 
    using System.Diagnostics;
    using System.Collections.Generic;
    using System.ComponentModel;
 
    internal enum Aggregate {
        None = FunctionId.none, 
        Sum = FunctionId.Sum, 
        Avg = FunctionId.Avg,
        Min = FunctionId.Min, 
        Max = FunctionId.Max,
        Count = FunctionId.Count,
        StDev = FunctionId.StDev,   // Statistical standard deviation
        Var = FunctionId.Var,       // Statistical variance 
    }
 
    internal sealed class AggregateNode : ExpressionNode { 
        private readonly AggregateType type;
        private readonly Aggregate aggregate; 
        private readonly bool local;     // set to true if the aggregate calculated localy (for the current table)

        private readonly string relationName;
        private readonly string columnName; 

        // 
 
        private DataTable childTable;
        private DataColumn column; 
        private DataRelation relation;

        internal AggregateNode(DataTable table, FunctionId aggregateType, string columnName) :
            this(table, aggregateType, columnName, true, null) { 
        }
 
        internal AggregateNode(DataTable table, FunctionId aggregateType, string columnName, string relationName) : 
            this(table, aggregateType, columnName, false, relationName) {
        } 

        internal AggregateNode(DataTable table, FunctionId aggregateType, string columnName, bool local, string relationName) : base(table) {
            Debug.Assert(columnName != null, "Invalid parameter column name (null).");
            this.aggregate = (Aggregate)(int)aggregateType; 

            if (aggregateType == FunctionId.Sum) 
                this.type = AggregateType.Sum; 
            else if (aggregateType == FunctionId.Avg)
                this.type = AggregateType.Mean; 
            else if (aggregateType == FunctionId.Min)
                this.type = AggregateType.Min;
            else if (aggregateType == FunctionId.Max)
                this.type = AggregateType.Max; 
            else if (aggregateType == FunctionId.Count)
                this.type = AggregateType.Count; 
            else if (aggregateType == FunctionId.Var) 
                this.type = AggregateType.Var;
            else if (aggregateType == FunctionId.StDev) 
                this.type = AggregateType.StDev;
            else {
                throw ExprException.UndefinedFunction(Function.FunctionName[(Int32)aggregateType]);
            } 

            this.local = local; 
            this.relationName = relationName; 
            this.columnName = columnName;
        } 
        internal override void Bind(DataTable table, List list) {
            BindTable(table);
            if (table == null)
                throw ExprException.AggregateUnbound(this.ToString()); 

            if (local) { 
                relation = null; 
            }
            else { 
                DataRelationCollection relations;
                relations = table.ChildRelations;

                if (relationName == null) { 
                    // must have one and only one relation
 
                    if (relations.Count > 1) { 
                        throw ExprException.UnresolvedRelation(table.TableName, this.ToString());
                    } 
                    if (relations.Count == 1) {
                        relation = relations[0];
                    }
                    else { 
                        throw ExprException.AggregateUnbound(this.ToString());
                    } 
                } 
                else {
                    relation = relations[relationName]; 
                }
            }

            childTable = (relation == null) ? table : relation.ChildTable; 

            this.column = childTable.Columns[columnName]; 
 
            if (column == null)
                throw ExprException.UnboundName(columnName); 

            // add column to the dependency list, do not add duplicate columns

            Debug.Assert(column != null, "Failed to bind column " + columnName); 

            int i; 
            for (i = 0; i < list.Count; i++) { 
                // walk the list, check if the current column already on the list
                DataColumn dataColumn = (DataColumn)list[i]; 
                if (column == dataColumn) {
                    break;
                }
            } 
            if (i >= list.Count) {
                list.Add(column); 
            } 

            // SQLBU 383715: Staleness of computed values in expression column as the relationship end columns are not being added to the dependent column list. 
            AggregateNode.Bind(relation, list);
        }

        internal static void Bind(DataRelation relation, List list) 
        {
            if (null != relation) { 
                // add the ends of the relationship the expression depends on 
                foreach (DataColumn c in relation.ChildColumnsReference) {
                    if (!list.Contains(c)) { 
                        list.Add(c);
                    }
                }
                foreach (DataColumn c in relation.ParentColumnsReference) { 
                    if (!list.Contains(c)) {
                        list.Add(c); 
                    } 
                }
            } 
        }

        internal override object Eval() {
            return Eval(null, DataRowVersion.Default); 
        }
 
        internal override object Eval(DataRow row, DataRowVersion version) { 
            if (childTable == null)
                throw ExprException.AggregateUnbound(this.ToString()); 

            DataRow[] rows;

            if (local) { 
                rows = new DataRow[childTable.Rows.Count];
                childTable.Rows.CopyTo(rows, 0); 
            } 
            else {
                if (row == null) { 
                    throw ExprException.EvalNoContext();
                }
                if (relation == null) {
                    throw ExprException.AggregateUnbound(this.ToString()); 
                }
                rows = row.GetChildRows(relation, version); 
            } 

            int[] records; 
            if (version == DataRowVersion.Proposed) {
                version = DataRowVersion.Default;
            }
 
            List recordList = new List();
 
            for (int i = 0; i < rows.Length; i++) { 
                if (rows[i].RowState == DataRowState.Deleted) {
                    if (DataRowAction.Rollback != rows[i]._action) { 
                        continue;
                    }
                    Debug.Assert(DataRowVersion.Original == version, "wrong version");
                    version = DataRowVersion.Original; 
                }
                else if ((DataRowAction.Rollback == rows[i]._action) && (rows[i].RowState == DataRowState.Added)) { 
                    continue; // WebData 91297 
                }
                if (version == DataRowVersion.Original && rows[i].oldRecord == -1) { 
                    continue;
                }
                recordList.Add(rows[i].GetRecordFromVersion(version));
            } 
            records = recordList.ToArray();
 
            return column.GetAggregateValue(records, type); 
        }
 
        // Helper for the DataTable.Compute method
        internal override object Eval(int[] records) {
            if (childTable == null)
                throw ExprException.AggregateUnbound(this.ToString()); 
            if (!local) {
                throw ExprException.ComputeNotAggregate(this.ToString()); 
            } 
            return column.GetAggregateValue(records, type);
        } 

        internal override bool IsConstant() {
            return false;
        } 

        internal override bool IsTableConstant() { 
            return local; 
        }
 
        internal override bool HasLocalAggregate() {
            return local;
        }
 
        internal override bool HasRemoteAggregate() {
            return !local; 
        } 

        internal override bool DependsOn(DataColumn column) { 
            if (this.column == column) {
                return true;
            }
            if (this.column.Computed) { 
                return this.column.DataExpression.DependsOn(column);
            } 
            return false; 
        }
 
        internal override ExpressionNode Optimize() {
            return this;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK