Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / SQLTypes / SQLInt64Storage.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SQLInt64Storage.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.Diagnostics;
15     using System.Globalization;
16     using System.IO;
17     using System.Xml.Serialization;
18     using System.Collections;
19
20     internal sealed class SqlInt64Storage : DataStorage {
21
22         private SqlInt64[] values;
23
24         public SqlInt64Storage(DataColumn column)
25         : base(column, typeof(SqlInt64), SqlInt64.Null, SqlInt64.Null, StorageType.SqlInt64) {
26         }
27
28         override public Object Aggregate(int[] records, AggregateType kind) {
29             bool hasData = false;
30             try {
31                 switch (kind) {
32                     case AggregateType.Sum:
33                         SqlInt64 sum =  0;
34                         foreach (int record in records) {
35                             if (IsNull(record))
36                                 continue;
37                             checked { sum += values[record];}
38                             hasData = true;
39                         }
40                         if (hasData) {
41                             return sum;
42                         }
43                         return NullValue;
44
45                     case AggregateType.Mean:
46                         SqlDecimal meanSum = 0;
47                         int meanCount = 0;
48                         foreach (int record in records) {
49                             if (IsNull(record))
50                                 continue;
51                             checked { meanSum += values[record].ToSqlDecimal();}
52                             meanCount++;
53                             hasData = true;
54                         }
55                         if (hasData) {
56                             SqlInt64 mean = 0;
57                             checked {mean = (meanSum /(SqlDecimal) meanCount).ToSqlInt64();}
58                             return mean;
59                         }
60                         return NullValue;
61
62                     case AggregateType.Var:
63                     case AggregateType.StDev:
64                         int count = 0;
65                         SqlDouble var = (SqlDouble)0;
66                         SqlDouble prec = (SqlDouble)0;
67                         SqlDouble dsum = (SqlDouble)0;
68                         SqlDouble sqrsum = (SqlDouble)0;
69
70                         foreach (int record in records) {
71                             if (IsNull(record))
72                                 continue;
73                             dsum += (values[record]).ToSqlDouble();
74                             sqrsum += (values[record]).ToSqlDouble() * (values[record]).ToSqlDouble();
75                             count++;
76                         }
77
78                         if (count > 1) {
79                             var = ((SqlDouble)count * sqrsum - (dsum * dsum));
80                             prec = var / (dsum * dsum);
81                             
82                             // we are dealing with the risk of a cancellation error
83                             // double is guaranteed only for 15 digits so a difference 
84                             // with a result less than 1e-15 should be considered as zero
85
86                             if ((prec < 1e-15) || (var <0))
87                                 var = 0;
88                             else
89                                 var = var / (count * (count -1));
90                             
91                             if (kind == AggregateType.StDev) {
92                                return  Math.Sqrt(var.Value);
93                             }
94                             return var;
95                         }
96                         return NullValue;
97
98                     case AggregateType.Min:
99                         SqlInt64 min = SqlInt64.MaxValue;
100                         for (int i = 0; i < records.Length; i++) {
101                             int record = records[i];
102                             if (IsNull(record))
103                                 continue;
104                             if ((SqlInt64.LessThan(values[record], min)).IsTrue)
105                                 min = values[record];                        
106                             hasData = true;
107                         }
108                         if (hasData) {
109                             return min;
110                         }
111                         return NullValue;
112
113                     case AggregateType.Max:
114                         SqlInt64 max = SqlInt64.MinValue;
115                         for (int i = 0; i < records.Length; i++) {
116                             int record = records[i];
117                             if (IsNull(record))
118                                 continue;
119
120                             if ((SqlInt64.GreaterThan(values[record], max)).IsTrue)
121                                 max = values[record];
122                             hasData = true;
123                         }
124                         if (hasData) {
125                             return max;
126                         }
127                         return NullValue;
128
129                     case AggregateType.First:
130                         if (records.Length > 0) {
131                             return values[records[0]];
132                         }
133                         return null;// no data => null
134
135                     case AggregateType.Count:
136                         count = 0;
137                         for (int i = 0; i < records.Length; i++) {
138                             if (!IsNull(records[i]))
139                                 count++;
140                         }
141                         return count;
142                 }
143             }
144             catch (OverflowException) {
145                 throw ExprException.Overflow(typeof(SqlInt64));
146             }
147             throw ExceptionBuilder.AggregateException(kind, DataType);
148         }
149
150         override public int Compare(int recordNo1, int recordNo2) {
151             return values[recordNo1].CompareTo(values[recordNo2]);
152         }
153
154         override public int CompareValueTo(int recordNo, Object value) {
155             return values[recordNo].CompareTo((SqlInt64)value);
156         }
157
158         override public object ConvertValue(object value) {
159             if (null != value) {
160                 return SqlConvert.ConvertToSqlInt64(value);
161             }
162             return NullValue;
163         }
164
165         override public void Copy(int recordNo1, int recordNo2) {
166             values[recordNo2] = values[recordNo1];
167         }
168
169         override public Object Get(int record) {
170             return values[record];
171         }
172
173         override public bool IsNull(int record) {
174             return (values[record].IsNull);
175         }
176
177         override public void Set(int record, Object value) {
178             values[record] = SqlConvert.ConvertToSqlInt64( value);
179         }
180
181         override public void SetCapacity(int capacity) {
182             SqlInt64[] newValues = new SqlInt64[capacity];
183             if (null != values) {
184                 Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length));
185             }
186             values = newValues;
187         }
188
189         override public object ConvertXmlToObject(string s) {
190             SqlInt64 newValue = new SqlInt64();
191             string tempStr =string.Concat("<col>", s, "</col>"); // this is done since you can give fragmet to reader, bug 98767
192             StringReader strReader = new  StringReader(tempStr);
193
194             IXmlSerializable tmp = newValue;
195             
196             using (XmlTextReader xmlTextReader = new XmlTextReader(strReader)) {
197                 tmp.ReadXml(xmlTextReader);
198             }
199             return ((SqlInt64)tmp);
200         }
201
202         override public string ConvertObjectToXml(object value) {
203             Debug.Assert(!DataStorage.IsObjectNull(value), "we shouldn't have null here");
204             Debug.Assert((value.GetType() == typeof(SqlInt64)), "wrong input type");
205             
206             StringWriter strwriter = new StringWriter(FormatProvider);
207
208             using (XmlTextWriter xmlTextWriter = new XmlTextWriter (strwriter)) {
209                 ((IXmlSerializable)value).WriteXml(xmlTextWriter);
210             }
211             return (strwriter.ToString ());
212         }
213         
214         override protected object GetEmptyStorage(int recordCount) {
215             return new SqlInt64[recordCount];
216         }
217
218         override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) {
219             SqlInt64[] typedStore = (SqlInt64[]) store; 
220             typedStore[storeIndex] = values[record];
221             nullbits.Set(storeIndex, IsNull(record));
222         }
223
224         override protected void SetStorage(object store, BitArray nullbits) {
225             values = (SqlInt64[]) store; 
226             //SetNullStorage(nullbits);
227         }        
228     }
229 }