Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / SQLTypes / SQLInt16Storage.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SQLInt16Storage.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 SqlInt16Storage : DataStorage {
21
22         private SqlInt16[] values;
23
24         public SqlInt16Storage(DataColumn column)
25         : base(column, typeof(SqlInt16), SqlInt16.Null, SqlInt16.Null, StorageType.SqlInt16) {
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                         SqlInt64 meanSum = 0;
47                         int meanCount = 0;
48                         foreach (int record in records) {
49                             if (IsNull(record))
50                                 continue;
51                             checked { meanSum += (values[record]).ToSqlInt64();}
52                             meanCount++;
53                             hasData = true;
54                         }
55                         if (hasData) {
56                             SqlInt16 mean = 0;
57                             checked {mean = (meanSum /(SqlInt64) meanCount).ToSqlInt16();}
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                         SqlInt16 min = SqlInt16.MaxValue;
100                         for (int i = 0; i < records.Length; i++) {
101                             int record = records[i];
102                             if (IsNull(record))
103                                 continue;
104                             if ((SqlInt16.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                         SqlInt16 max = SqlInt16.MinValue;
115                         for (int i = 0; i < records.Length; i++) {
116                             int record = records[i];
117                             if (IsNull(record))
118                                 continue;
119                             if ((SqlInt16.GreaterThan(values[record], max)).IsTrue)
120                                 max = values[record];
121                             hasData = true;
122                         }
123                         if (hasData) {
124                             return max;
125                         }
126                         return NullValue;
127
128                     case AggregateType.First:
129                         if (records.Length > 0) {
130                             return values[records[0]];
131                         }
132                         return null;// no data => null
133
134                     case AggregateType.Count:
135                         count = 0;
136                         for (int i = 0; i < records.Length; i++) {
137                             if (!IsNull(records[i]))
138                                 count++;
139                         }
140                         return count;
141                 }
142             }
143             catch (OverflowException) {
144                 throw ExprException.Overflow(typeof(SqlInt16));
145             }
146             throw ExceptionBuilder.AggregateException(kind, DataType);
147         }
148
149         override public int Compare(int recordNo1, int recordNo2) {
150             return values[recordNo1].CompareTo(values[recordNo2]);
151         }
152
153         override public int CompareValueTo(int recordNo, Object value) {
154             return values[recordNo].CompareTo((SqlInt16)value);
155         }
156
157         override public object ConvertValue(object value) {
158             if (null != value) {
159                 return SqlConvert.ConvertToSqlInt16(value);
160             }
161             return NullValue;
162         }
163
164         override public void Copy(int recordNo1, int recordNo2) {
165             values[recordNo2] = values[recordNo1];
166         }
167
168         override public Object Get(int record) {
169             return values[record];
170         }
171
172         override public bool IsNull(int record) {
173             return (values[record].IsNull);
174         }
175
176         override public void Set(int record, Object value) {
177             values[record] = SqlConvert.ConvertToSqlInt16( value);
178         }
179
180         override public void SetCapacity(int capacity) {
181             SqlInt16[] newValues = new SqlInt16[capacity];
182             if (null != values) {
183                 Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length));
184             }
185             values = newValues;
186         }
187
188         override public object ConvertXmlToObject(string s) {
189             SqlInt16 newValue = new SqlInt16();
190             string tempStr =string.Concat("<col>", s, "</col>"); // this is done since you can give fragmet to reader, bug 98767
191             StringReader strReader = new  StringReader(tempStr);
192
193             IXmlSerializable tmp = newValue;
194             
195             using (XmlTextReader xmlTextReader = new XmlTextReader(strReader)) {
196                 tmp.ReadXml(xmlTextReader);
197             }
198             return ((SqlInt16)tmp);
199         }
200
201         override public string ConvertObjectToXml(object value) {
202             Debug.Assert(!DataStorage.IsObjectNull(value), "we shouldn't have null here");
203             Debug.Assert((value.GetType() == typeof(SqlInt16)), "wrong input type");
204             
205             StringWriter strwriter = new StringWriter(FormatProvider);
206
207             using (XmlTextWriter xmlTextWriter = new XmlTextWriter (strwriter)) {
208                 ((IXmlSerializable)value).WriteXml(xmlTextWriter);
209             }
210             return (strwriter.ToString ());
211         }
212         
213         override protected object GetEmptyStorage(int recordCount) {
214             return new SqlInt16[recordCount];
215         }
216         
217         override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) {
218             SqlInt16[] typedStore = (SqlInt16[]) store; 
219             typedStore[storeIndex] = values[record];
220             nullbits.Set(storeIndex, IsNull(record));
221         }
222         
223         override protected void SetStorage(object store, BitArray nullbits) {
224             values = (SqlInt16[]) store; 
225             //SetNullStorage(nullbits);
226         }         
227     }
228 }