1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Xml; 6 using System.Collections; 7 8 namespace System.Data.Common 9 { 10 internal sealed class DateTimeOffsetStorage : DataStorage 11 { 12 private static readonly DateTimeOffset s_defaultValue = DateTimeOffset.MinValue; 13 14 private DateTimeOffset[] _values; 15 DateTimeOffsetStorage(DataColumn column)16 internal DateTimeOffsetStorage(DataColumn column) 17 : base(column, typeof(DateTimeOffset), s_defaultValue, StorageType.DateTimeOffset) 18 { 19 } 20 Aggregate(int[] records, AggregateType kind)21 public override object Aggregate(int[] records, AggregateType kind) 22 { 23 bool hasData = false; 24 try 25 { 26 switch (kind) 27 { 28 case AggregateType.Min: 29 DateTimeOffset min = DateTimeOffset.MaxValue; 30 for (int i = 0; i < records.Length; i++) 31 { 32 int record = records[i]; 33 if (HasValue(record)) 34 { 35 min = (DateTimeOffset.Compare(_values[record], min) < 0) ? _values[record] : min; 36 hasData = true; 37 } 38 } 39 if (hasData) 40 { 41 return min; 42 } 43 return _nullValue; 44 45 case AggregateType.Max: 46 DateTimeOffset max = DateTimeOffset.MinValue; 47 for (int i = 0; i < records.Length; i++) 48 { 49 int record = records[i]; 50 if (HasValue(record)) 51 { 52 max = (DateTimeOffset.Compare(_values[record], max) >= 0) ? _values[record] : max; 53 hasData = true; 54 } 55 } 56 if (hasData) 57 { 58 return max; 59 } 60 return _nullValue; 61 62 case AggregateType.First: 63 if (records.Length > 0) 64 { 65 return _values[records[0]]; 66 } 67 return null; 68 69 case AggregateType.Count: 70 int count = 0; 71 for (int i = 0; i < records.Length; i++) 72 { 73 if (HasValue(records[i])) 74 { 75 count++; 76 } 77 } 78 return count; 79 } 80 } 81 catch (OverflowException) 82 { 83 throw ExprException.Overflow(typeof(DateTimeOffset)); 84 } 85 throw ExceptionBuilder.AggregateException(kind, _dataType); 86 } 87 Compare(int recordNo1, int recordNo2)88 public override int Compare(int recordNo1, int recordNo2) 89 { 90 DateTimeOffset valueNo1 = _values[recordNo1]; 91 DateTimeOffset valueNo2 = _values[recordNo2]; 92 93 if (valueNo1 == s_defaultValue || valueNo2 == s_defaultValue) 94 { 95 int bitCheck = CompareBits(recordNo1, recordNo2); 96 if (0 != bitCheck) 97 { 98 return bitCheck; 99 } 100 } 101 return DateTimeOffset.Compare(valueNo1, valueNo2); 102 } 103 CompareValueTo(int recordNo, object value)104 public override int CompareValueTo(int recordNo, object value) 105 { 106 System.Diagnostics.Debug.Assert(0 <= recordNo, "Invalid record"); 107 System.Diagnostics.Debug.Assert(null != value, "null value"); 108 109 if (_nullValue == value) 110 { 111 return (HasValue(recordNo) ? 1 : 0); 112 } 113 114 DateTimeOffset valueNo1 = _values[recordNo]; 115 if ((s_defaultValue == valueNo1) && !HasValue(recordNo)) 116 { 117 return -1; 118 } 119 return DateTimeOffset.Compare(valueNo1, (DateTimeOffset)value); 120 } 121 ConvertValue(object value)122 public override object ConvertValue(object value) 123 { 124 if (_nullValue != value) 125 { 126 if (null != value) 127 { 128 value = ((DateTimeOffset)value); 129 } 130 else 131 { 132 value = _nullValue; 133 } 134 } 135 return value; 136 } 137 Copy(int recordNo1, int recordNo2)138 public override void Copy(int recordNo1, int recordNo2) 139 { 140 CopyBits(recordNo1, recordNo2); 141 _values[recordNo2] = _values[recordNo1]; 142 } 143 Get(int record)144 public override object Get(int record) 145 { 146 DateTimeOffset value = _values[record]; 147 if ((value != s_defaultValue) || HasValue(record)) 148 { 149 return value; 150 } 151 return _nullValue; 152 } 153 Set(int record, object value)154 public override void Set(int record, object value) 155 { 156 System.Diagnostics.Debug.Assert(null != value, "null value"); 157 if (_nullValue == value) 158 { 159 _values[record] = s_defaultValue; 160 SetNullBit(record, true); 161 } 162 else 163 { 164 _values[record] = (DateTimeOffset)value; 165 SetNullBit(record, false); 166 } 167 } 168 SetCapacity(int capacity)169 public override void SetCapacity(int capacity) 170 { 171 DateTimeOffset[] newValues = new DateTimeOffset[capacity]; 172 if (null != _values) 173 { 174 Array.Copy(_values, 0, newValues, 0, Math.Min(capacity, _values.Length)); 175 } 176 _values = newValues; 177 base.SetCapacity(capacity); 178 } 179 ConvertXmlToObject(string s)180 public override object ConvertXmlToObject(string s) 181 { 182 return XmlConvert.ToDateTimeOffset(s); 183 } 184 ConvertObjectToXml(object value)185 public override string ConvertObjectToXml(object value) 186 { 187 return XmlConvert.ToString((DateTimeOffset)value); 188 } 189 GetEmptyStorage(int recordCount)190 protected override object GetEmptyStorage(int recordCount) 191 { 192 return new DateTimeOffset[recordCount]; 193 } 194 CopyValue(int record, object store, BitArray nullbits, int storeIndex)195 protected override void CopyValue(int record, object store, BitArray nullbits, int storeIndex) 196 { 197 DateTimeOffset[] typedStore = (DateTimeOffset[])store; 198 typedStore[storeIndex] = _values[record]; 199 nullbits.Set(storeIndex, !HasValue(record)); 200 } 201 SetStorage(object store, BitArray nullbits)202 protected override void SetStorage(object store, BitArray nullbits) 203 { 204 _values = (DateTimeOffset[])store; 205 SetNullStorage(nullbits); 206 } 207 } 208 } 209