b46bf5fb2eb581963aae9d19f97ce0db054a80b6
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / TimeSpanStorage.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="TimeSpanStorage.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 // <owner current="false" primary="false">Microsoft</owner>
8 //------------------------------------------------------------------------------
9
10 namespace System.Data.Common {
11     using System;
12     using System.Xml;
13     using System.Data.SqlTypes;
14     using System.Collections;
15
16     internal sealed class TimeSpanStorage : DataStorage {
17
18         private static readonly TimeSpan defaultValue = TimeSpan.Zero;
19
20         private TimeSpan[] values;
21
22         public TimeSpanStorage(DataColumn column)
23         : base(column, typeof(TimeSpan), defaultValue, StorageType.TimeSpan) {
24         }
25
26         override public Object Aggregate(int[] records, AggregateType kind) {
27             bool hasData = false;
28             try {
29                 switch (kind) {
30                     case AggregateType.Min:
31                         TimeSpan min = TimeSpan.MaxValue;
32                         for (int i = 0; i < records.Length; i++) {
33                             int record = records[i];
34                             if (IsNull(record))
35                                 continue;
36                             min=(TimeSpan.Compare(values[record],min) < 0) ? values[record] : min;
37                             hasData = true;
38                         }
39                         if (hasData) {
40                             return min;
41                         }
42                         return NullValue;
43
44                     case AggregateType.Max:
45                         TimeSpan max = TimeSpan.MinValue;
46                         for (int i = 0; i < records.Length; i++) {
47                             int record = records[i];
48                             if (IsNull(record))
49                                 continue;
50                             max=(TimeSpan.Compare(values[record],max) >= 0) ? values[record] : max;
51                             hasData = true;
52                         }
53                         if (hasData) {
54                             return max;
55                         }
56                         return NullValue;
57
58                     case AggregateType.First:
59                         if (records.Length > 0) {
60                             return values[records[0]];
61                         }
62                         return null;
63
64                     case AggregateType.Count:
65                         return base.Aggregate(records, kind);
66
67                     case AggregateType.Sum: {
68                             decimal sum = 0;
69                             foreach (int record in records) {
70                                 if (IsNull(record))
71                                     continue;
72                                 sum += values[record].Ticks; 
73                                 hasData = true;
74                             }
75                             if (hasData) {
76                                 return TimeSpan.FromTicks((long)Math.Round(sum));
77                             }
78                             return null;
79                         }
80
81                     case AggregateType.Mean: {
82                             decimal meanSum = 0;
83                             int meanCount = 0;
84                             foreach (int record in records) {
85                                 if (IsNull(record))
86                                     continue;
87                                 meanSum += values[record].Ticks; 
88                                 meanCount++;
89                             }
90                             if (meanCount > 0) {
91                                 return TimeSpan.FromTicks((long)Math.Round(meanSum / meanCount));
92                             }
93                             return null;
94                         }
95
96                     case AggregateType.StDev: {
97                            int count = 0;
98                             decimal meanSum = 0;                            
99
100                             foreach (int record in records) {
101                                 if (IsNull(record))
102                                     continue;
103                                 meanSum += values[record].Ticks; 
104                                 count++;
105                             }
106
107                             if (count > 1) {
108                                 double varSum = 0;
109                                 decimal mean=meanSum/count;
110                                 foreach (int record in records) {
111                                     if (IsNull(record))
112                                         continue;
113                                     double x = (double)(values[record].Ticks - mean);
114                                     varSum += x * x;
115                                 }
116                                 ulong stDev = (ulong)Math.Round(Math.Sqrt(varSum / (count - 1)));
117                                 if (stDev > long.MaxValue) {
118                                     stDev = long.MaxValue;
119                                 }
120                                 return TimeSpan.FromTicks((long)stDev);
121                             }
122                             return null;
123                         }
124                 }
125             }
126             catch (OverflowException) {
127                 throw ExprException.Overflow(typeof(TimeSpan));
128             }
129             throw ExceptionBuilder.AggregateException(kind, DataType);
130         }
131
132         override public int Compare(int recordNo1, int recordNo2) {
133             TimeSpan valueNo1 = values[recordNo1];
134             TimeSpan valueNo2 = values[recordNo2];
135
136             if (valueNo1 == defaultValue || valueNo2 == defaultValue) {
137                 int bitCheck = CompareBits(recordNo1, recordNo2);
138                 if (0 != bitCheck)
139                     return bitCheck;
140             }
141             return TimeSpan.Compare(valueNo1, valueNo2);
142         }
143
144         public override int CompareValueTo(int recordNo, object value) {
145             System.Diagnostics.Debug.Assert(0 <= recordNo, "Invalid record");
146             System.Diagnostics.Debug.Assert(null != value, "null value");
147
148             if (NullValue == value) {
149                 if (IsNull(recordNo)) {
150                     return 0;
151                 }
152                 return 1;
153             }
154
155             TimeSpan valueNo1 = values[recordNo];
156             if ((defaultValue == valueNo1) && IsNull(recordNo)) {
157                 return -1;
158             }
159             return valueNo1.CompareTo((TimeSpan)value);
160         }
161
162         private static TimeSpan ConvertToTimeSpan(object value) {
163             // Webdata 94686: Do not change this checks
164             Type typeofValue= value.GetType();
165
166             if (typeofValue == typeof(string)) {
167                 return TimeSpan.Parse((string)value);
168             }
169             else if (typeofValue == typeof(Int32)) {
170                 return new TimeSpan((Int64)((Int32)value));
171             }
172             else if (typeofValue == typeof(Int64))  {
173                 return new TimeSpan((Int64)value);
174             }
175             else {
176                 return (TimeSpan) value;
177             }
178         }
179
180         public override object ConvertValue(object value) {
181             if (NullValue != value) {
182                 if (null != value) {
183                     value = ConvertToTimeSpan(value);
184                 }
185                 else {
186                     value = NullValue;
187                 }
188             }
189             return value;
190         }
191
192
193         override public void Copy(int recordNo1, int recordNo2) {
194             CopyBits(recordNo1, recordNo2);
195             values[recordNo2] = values[recordNo1];
196         }
197
198         override public Object Get(int record) {
199             TimeSpan value = values[record];
200             if (value != defaultValue) {
201                 return value;
202             }
203             return GetBits(record);
204         }
205
206         override public void Set(int record, Object value) {
207             System.Diagnostics.Debug.Assert(null != value, "null value");
208             if (NullValue == value) {
209                 values[record] = defaultValue;
210                 SetNullBit(record, true);
211             }
212             else {
213                 values[record] = ConvertToTimeSpan(value);
214                 SetNullBit(record, false);
215             }
216         }
217
218         override public void SetCapacity(int capacity) {
219             TimeSpan[] newValues = new TimeSpan[capacity];
220             if (null != values) {
221                 Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length));
222             }
223             values = newValues;
224             base.SetCapacity(capacity);
225         }
226
227         override public object ConvertXmlToObject(string s) {
228             return XmlConvert.ToTimeSpan(s);
229         }
230
231         override public string ConvertObjectToXml(object value) {
232             return XmlConvert.ToString((TimeSpan)value);
233         }
234
235         override protected object GetEmptyStorage(int recordCount) {
236             return new TimeSpan[recordCount];
237         }
238
239         override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) {
240             TimeSpan[] typedStore = (TimeSpan[]) store;
241             typedStore[storeIndex] = values[record];
242             nullbits.Set(storeIndex, IsNull(record));
243         }
244
245         override protected void SetStorage(object store, BitArray nullbits) {
246             values = (TimeSpan[]) store;
247             SetNullStorage(nullbits);
248         }
249     }
250 }