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 
6 
7 
8 
9 //------------------------------------------------------------------------------
10 
11 using System;
12 using System.Data;
13 using System.Data.Common;
14 using System.Data.ProviderBase;
15 using System.Data.SqlTypes;
16 using System.Data.SqlClient;
17 using System.Diagnostics;
18 
19 namespace Microsoft.SqlServer.Server
20 {
21     public class SqlDataRecord : IDataRecord
22     {
23         private SmiRecordBuffer _recordBuffer;
24         private SmiExtendedMetaData[] _columnSmiMetaData;
25         private SmiEventSink_Default _eventSink;
26         private SqlMetaData[] _columnMetaData;
27         private FieldNameLookup _fieldNameLookup;
28         private bool _usesStringStorageForXml;
29 
30         private static readonly SmiMetaData s_maxNVarCharForXml = new SmiMetaData(SqlDbType.NVarChar, SmiMetaData.UnlimitedMaxLengthIndicator,
31                                         SmiMetaData.DefaultNVarChar_NoCollation.Precision,
32                                         SmiMetaData.DefaultNVarChar_NoCollation.Scale,
33                                         SmiMetaData.DefaultNVarChar.LocaleId,
34                                         SmiMetaData.DefaultNVarChar.CompareOptions,
35                                         null);
36 
37         public virtual int FieldCount
38         {
39             get
40             {
41                 EnsureSubclassOverride();
42                 return _columnMetaData.Length;
43             }
44         }
45 
GetName(int ordinal)46         public virtual String GetName(int ordinal)
47         {
48             EnsureSubclassOverride();
49             return GetSqlMetaData(ordinal).Name;
50         }
51 
GetDataTypeName(int ordinal)52         public virtual String GetDataTypeName(int ordinal)
53         {
54             EnsureSubclassOverride();
55             SqlMetaData metaData = GetSqlMetaData(ordinal);
56             if (SqlDbType.Udt == metaData.SqlDbType)
57             {
58                 return metaData.UdtTypeName;
59             }
60             else
61             {
62                 return MetaType.GetMetaTypeFromSqlDbType(metaData.SqlDbType, false).TypeName;
63             }
64         }
65 
GetFieldType(int ordinal)66         public virtual Type GetFieldType(int ordinal)
67         {
68             EnsureSubclassOverride();
69             {
70                 SqlMetaData md = GetSqlMetaData(ordinal);
71                 return MetaType.GetMetaTypeFromSqlDbType(md.SqlDbType, false).ClassType;
72             }
73         }
74 
GetValue(int ordinal)75         public virtual Object GetValue(int ordinal)
76         {
77             EnsureSubclassOverride();
78             SmiMetaData metaData = GetSmiMetaData(ordinal);
79 
80             return ValueUtilsSmi.GetValue200(
81                             _eventSink,
82                             _recordBuffer,
83                             ordinal,
84                             metaData
85                                 );
86         }
87 
GetValues(object[] values)88         public virtual int GetValues(object[] values)
89         {
90             EnsureSubclassOverride();
91             if (null == values)
92             {
93                 throw ADP.ArgumentNull(nameof(values));
94             }
95 
96             int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount;
97             for (int i = 0; i < copyLength; i++)
98             {
99                 values[i] = GetValue(i);
100             }
101 
102             return copyLength;
103         }
104 
GetOrdinal(string name)105         public virtual int GetOrdinal(string name)
106         {
107             EnsureSubclassOverride();
108             if (null == _fieldNameLookup)
109             {
110                 string[] names = new string[FieldCount];
111                 for (int i = 0; i < names.Length; i++)
112                 {
113                     names[i] = GetSqlMetaData(i).Name;
114                 }
115 
116                 _fieldNameLookup = new FieldNameLookup(names, -1);
117             }
118 
119             return _fieldNameLookup.GetOrdinal(name);
120         }
121 
122         public virtual object this[int ordinal]
123         {
124             get
125             {
126                 EnsureSubclassOverride();
127                 return GetValue(ordinal);
128             }
129         }
130 
131         public virtual object this[String name]
132         {
133             get
134             {
135                 EnsureSubclassOverride();
136                 return GetValue(GetOrdinal(name));
137             }
138         }
139 
GetBoolean(int ordinal)140         public virtual bool GetBoolean(int ordinal)
141         {
142             EnsureSubclassOverride();
143             return ValueUtilsSmi.GetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
144         }
145 
GetByte(int ordinal)146         public virtual byte GetByte(int ordinal)
147         {
148             EnsureSubclassOverride();
149             return ValueUtilsSmi.GetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
150         }
151 
GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)152         public virtual long GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)
153         {
154             EnsureSubclassOverride();
155             return ValueUtilsSmi.GetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length, true);
156         }
157 
GetChar(int ordinal)158         public virtual char GetChar(int ordinal)
159         {
160             EnsureSubclassOverride();
161             throw ADP.NotSupported();
162         }
163 
GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)164         public virtual long GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)
165         {
166             EnsureSubclassOverride();
167             return ValueUtilsSmi.GetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length);
168         }
169 
GetGuid(int ordinal)170         public virtual Guid GetGuid(int ordinal)
171         {
172             EnsureSubclassOverride();
173             return ValueUtilsSmi.GetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
174         }
175 
GetInt16(int ordinal)176         public virtual Int16 GetInt16(int ordinal)
177         {
178             EnsureSubclassOverride();
179             return ValueUtilsSmi.GetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
180         }
181 
GetInt32(int ordinal)182         public virtual Int32 GetInt32(int ordinal)
183         {
184             EnsureSubclassOverride();
185             return ValueUtilsSmi.GetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
186         }
187 
GetInt64(int ordinal)188         public virtual Int64 GetInt64(int ordinal)
189         {
190             EnsureSubclassOverride();
191             return ValueUtilsSmi.GetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
192         }
193 
GetFloat(int ordinal)194         public virtual float GetFloat(int ordinal)
195         {
196             EnsureSubclassOverride();
197             return ValueUtilsSmi.GetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
198         }
199 
GetDouble(int ordinal)200         public virtual double GetDouble(int ordinal)
201         {
202             EnsureSubclassOverride();
203             return ValueUtilsSmi.GetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
204         }
205 
GetString(int ordinal)206         public virtual string GetString(int ordinal)
207         {
208             EnsureSubclassOverride();
209             SmiMetaData colMeta = GetSmiMetaData(ordinal);
210             if (_usesStringStorageForXml && SqlDbType.Xml == colMeta.SqlDbType)
211             {
212                 return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, s_maxNVarCharForXml);
213             }
214             else
215             {
216                 return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
217             }
218         }
219 
GetDecimal(int ordinal)220         public virtual Decimal GetDecimal(int ordinal)
221         {
222             EnsureSubclassOverride();
223             return ValueUtilsSmi.GetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
224         }
225 
GetDateTime(int ordinal)226         public virtual DateTime GetDateTime(int ordinal)
227         {
228             EnsureSubclassOverride();
229             return ValueUtilsSmi.GetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
230         }
231 
GetDateTimeOffset(int ordinal)232         public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
233         {
234             EnsureSubclassOverride();
235             return ValueUtilsSmi.GetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
236         }
237 
GetTimeSpan(int ordinal)238         public virtual TimeSpan GetTimeSpan(int ordinal)
239         {
240             EnsureSubclassOverride();
241             return ValueUtilsSmi.GetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
242         }
243 
244 
IsDBNull(int ordinal)245         public virtual bool IsDBNull(int ordinal)
246         {
247             EnsureSubclassOverride();
248             ThrowIfInvalidOrdinal(ordinal);
249             return ValueUtilsSmi.IsDBNull(_eventSink, _recordBuffer, ordinal);
250         }
251 
252         //
253         //  ISqlRecord implementation
254         //
GetSqlMetaData(int ordinal)255         public virtual SqlMetaData GetSqlMetaData(int ordinal)
256         {
257             EnsureSubclassOverride();
258             return _columnMetaData[ordinal];
259         }
260 
GetSqlFieldType(int ordinal)261         public virtual Type GetSqlFieldType(int ordinal)
262         {
263             EnsureSubclassOverride();
264             SqlMetaData md = GetSqlMetaData(ordinal);
265             return MetaType.GetMetaTypeFromSqlDbType(md.SqlDbType, false).SqlType;
266         }
267 
GetSqlValue(int ordinal)268         public virtual object GetSqlValue(int ordinal)
269         {
270             EnsureSubclassOverride();
271             SmiMetaData metaData = GetSmiMetaData(ordinal);
272             return ValueUtilsSmi.GetSqlValue200(_eventSink, _recordBuffer, ordinal, metaData);
273         }
274 
GetSqlValues(object[] values)275         public virtual int GetSqlValues(object[] values)
276         {
277             EnsureSubclassOverride();
278             if (null == values)
279             {
280                 throw ADP.ArgumentNull(nameof(values));
281             }
282 
283 
284             int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount;
285             for (int i = 0; i < copyLength; i++)
286             {
287                 values[i] = GetSqlValue(i);
288             }
289 
290             return copyLength;
291         }
292 
GetSqlBinary(int ordinal)293         public virtual SqlBinary GetSqlBinary(int ordinal)
294         {
295             EnsureSubclassOverride();
296             return ValueUtilsSmi.GetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
297         }
298 
GetSqlBytes(int ordinal)299         public virtual SqlBytes GetSqlBytes(int ordinal)
300         {
301             EnsureSubclassOverride();
302             return ValueUtilsSmi.GetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
303         }
304 
GetSqlXml(int ordinal)305         public virtual SqlXml GetSqlXml(int ordinal)
306         {
307             EnsureSubclassOverride();
308             return ValueUtilsSmi.GetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
309         }
310 
GetSqlBoolean(int ordinal)311         public virtual SqlBoolean GetSqlBoolean(int ordinal)
312         {
313             EnsureSubclassOverride();
314             return ValueUtilsSmi.GetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
315         }
316 
GetSqlByte(int ordinal)317         public virtual SqlByte GetSqlByte(int ordinal)
318         {
319             EnsureSubclassOverride();
320             return ValueUtilsSmi.GetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
321         }
322 
GetSqlChars(int ordinal)323         public virtual SqlChars GetSqlChars(int ordinal)
324         {
325             EnsureSubclassOverride();
326             return ValueUtilsSmi.GetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
327         }
328 
GetSqlInt16(int ordinal)329         public virtual SqlInt16 GetSqlInt16(int ordinal)
330         {
331             EnsureSubclassOverride();
332             return ValueUtilsSmi.GetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
333         }
334 
GetSqlInt32(int ordinal)335         public virtual SqlInt32 GetSqlInt32(int ordinal)
336         {
337             EnsureSubclassOverride();
338             return ValueUtilsSmi.GetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
339         }
340 
GetSqlInt64(int ordinal)341         public virtual SqlInt64 GetSqlInt64(int ordinal)
342         {
343             EnsureSubclassOverride();
344             return ValueUtilsSmi.GetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
345         }
346 
GetSqlSingle(int ordinal)347         public virtual SqlSingle GetSqlSingle(int ordinal)
348         {
349             EnsureSubclassOverride();
350             return ValueUtilsSmi.GetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
351         }
352 
GetSqlDouble(int ordinal)353         public virtual SqlDouble GetSqlDouble(int ordinal)
354         {
355             EnsureSubclassOverride();
356             return ValueUtilsSmi.GetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
357         }
358 
GetSqlMoney(int ordinal)359         public virtual SqlMoney GetSqlMoney(int ordinal)
360         {
361             EnsureSubclassOverride();
362             return ValueUtilsSmi.GetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
363         }
364 
GetSqlDateTime(int ordinal)365         public virtual SqlDateTime GetSqlDateTime(int ordinal)
366         {
367             EnsureSubclassOverride();
368             return ValueUtilsSmi.GetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
369         }
370 
GetSqlDecimal(int ordinal)371         public virtual SqlDecimal GetSqlDecimal(int ordinal)
372         {
373             EnsureSubclassOverride();
374             return ValueUtilsSmi.GetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
375         }
376 
GetSqlString(int ordinal)377         public virtual SqlString GetSqlString(int ordinal)
378         {
379             EnsureSubclassOverride();
380             return ValueUtilsSmi.GetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
381         }
382 
GetSqlGuid(int ordinal)383         public virtual SqlGuid GetSqlGuid(int ordinal)
384         {
385             EnsureSubclassOverride();
386             return ValueUtilsSmi.GetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal));
387         }
388 
389         //
390         // ISqlUpdateableRecord Implementation
391         //
SetValues(params object[] values)392         public virtual int SetValues(params object[] values)
393         {
394             EnsureSubclassOverride();
395             if (null == values)
396             {
397                 throw ADP.ArgumentNull(nameof(values));
398             }
399 
400             // Allow values array longer than FieldCount, just ignore the extra cells.
401             int copyLength = (values.Length > FieldCount) ? FieldCount : values.Length;
402 
403             ExtendedClrTypeCode[] typeCodes = new ExtendedClrTypeCode[copyLength];
404 
405             // Verify all data values as acceptable before changing current state.
406             for (int i = 0; i < copyLength; i++)
407             {
408                 SqlMetaData metaData = GetSqlMetaData(i);
409                 typeCodes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(
410                     metaData.SqlDbType, false /* isMultiValued */, values[i], metaData.Type);
411                 if (ExtendedClrTypeCode.Invalid == typeCodes[i])
412                 {
413                     throw ADP.InvalidCast();
414                 }
415             }
416 
417             // Now move the data (it'll only throw if someone plays with the values array between
418             //      the validation loop and here, or if an invalid UDT was sent).
419             for (int i = 0; i < copyLength; i++)
420             {
421                 ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], 0, 0, null);
422             }
423 
424             return copyLength;
425         }
426 
SetValue(int ordinal, object value)427         public virtual void SetValue(int ordinal, object value)
428         {
429             EnsureSubclassOverride();
430             SqlMetaData metaData = GetSqlMetaData(ordinal);
431             ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(
432                         metaData.SqlDbType, false /* isMultiValued */, value, metaData.Type);
433             if (ExtendedClrTypeCode.Invalid == typeCode)
434             {
435                 throw ADP.InvalidCast();
436             }
437 
438             ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, 0, 0, null);
439         }
440 
SetBoolean(int ordinal, bool value)441         public virtual void SetBoolean(int ordinal, bool value)
442         {
443             EnsureSubclassOverride();
444             ValueUtilsSmi.SetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
445         }
446 
SetByte(int ordinal, byte value)447         public virtual void SetByte(int ordinal, byte value)
448         {
449             EnsureSubclassOverride();
450             ValueUtilsSmi.SetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
451         }
452 
SetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)453         public virtual void SetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length)
454         {
455             EnsureSubclassOverride();
456             ValueUtilsSmi.SetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length);
457         }
458 
SetChar(int ordinal, char value)459         public virtual void SetChar(int ordinal, char value)
460         {
461             EnsureSubclassOverride();
462             throw ADP.NotSupported();
463         }
464 
SetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)465         public virtual void SetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length)
466         {
467             EnsureSubclassOverride();
468             ValueUtilsSmi.SetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length);
469         }
470 
SetInt16(int ordinal, System.Int16 value)471         public virtual void SetInt16(int ordinal, System.Int16 value)
472         {
473             EnsureSubclassOverride();
474             ValueUtilsSmi.SetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
475         }
476 
SetInt32(int ordinal, System.Int32 value)477         public virtual void SetInt32(int ordinal, System.Int32 value)
478         {
479             EnsureSubclassOverride();
480             ValueUtilsSmi.SetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
481         }
482 
SetInt64(int ordinal, System.Int64 value)483         public virtual void SetInt64(int ordinal, System.Int64 value)
484         {
485             EnsureSubclassOverride();
486             ValueUtilsSmi.SetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
487         }
488 
SetFloat(int ordinal, float value)489         public virtual void SetFloat(int ordinal, float value)
490         {
491             EnsureSubclassOverride();
492             ValueUtilsSmi.SetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
493         }
494 
SetDouble(int ordinal, double value)495         public virtual void SetDouble(int ordinal, double value)
496         {
497             EnsureSubclassOverride();
498             ValueUtilsSmi.SetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
499         }
500 
SetString(int ordinal, string value)501         public virtual void SetString(int ordinal, string value)
502         {
503             EnsureSubclassOverride();
504             ValueUtilsSmi.SetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
505         }
506 
SetDecimal(int ordinal, Decimal value)507         public virtual void SetDecimal(int ordinal, Decimal value)
508         {
509             EnsureSubclassOverride();
510             ValueUtilsSmi.SetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
511         }
512 
SetDateTime(int ordinal, DateTime value)513         public virtual void SetDateTime(int ordinal, DateTime value)
514         {
515             EnsureSubclassOverride();
516             ValueUtilsSmi.SetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
517         }
518 
SetTimeSpan(int ordinal, TimeSpan value)519         public virtual void SetTimeSpan(int ordinal, TimeSpan value)
520         {
521             EnsureSubclassOverride();
522             ValueUtilsSmi.SetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
523         }
524 
SetDateTimeOffset(int ordinal, DateTimeOffset value)525         public virtual void SetDateTimeOffset(int ordinal, DateTimeOffset value)
526         {
527             EnsureSubclassOverride();
528             ValueUtilsSmi.SetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
529         }
530 
SetDBNull(int ordinal)531         public virtual void SetDBNull(int ordinal)
532         {
533             EnsureSubclassOverride();
534             ValueUtilsSmi.SetDBNull(_eventSink, _recordBuffer, ordinal, true);
535         }
536 
SetGuid(int ordinal, Guid value)537         public virtual void SetGuid(int ordinal, Guid value)
538         {
539             EnsureSubclassOverride();
540             ValueUtilsSmi.SetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
541         }
542 
SetSqlBoolean(int ordinal, SqlBoolean value)543         public virtual void SetSqlBoolean(int ordinal, SqlBoolean value)
544         {
545             EnsureSubclassOverride();
546             ValueUtilsSmi.SetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
547         }
548 
SetSqlByte(int ordinal, SqlByte value)549         public virtual void SetSqlByte(int ordinal, SqlByte value)
550         {
551             EnsureSubclassOverride();
552             ValueUtilsSmi.SetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
553         }
554 
SetSqlInt16(int ordinal, SqlInt16 value)555         public virtual void SetSqlInt16(int ordinal, SqlInt16 value)
556         {
557             EnsureSubclassOverride();
558             ValueUtilsSmi.SetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
559         }
560 
SetSqlInt32(int ordinal, SqlInt32 value)561         public virtual void SetSqlInt32(int ordinal, SqlInt32 value)
562         {
563             EnsureSubclassOverride();
564             ValueUtilsSmi.SetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
565         }
566 
SetSqlInt64(int ordinal, SqlInt64 value)567         public virtual void SetSqlInt64(int ordinal, SqlInt64 value)
568         {
569             EnsureSubclassOverride();
570             ValueUtilsSmi.SetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
571         }
572 
SetSqlSingle(int ordinal, SqlSingle value)573         public virtual void SetSqlSingle(int ordinal, SqlSingle value)
574         {
575             EnsureSubclassOverride();
576             ValueUtilsSmi.SetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
577         }
578 
SetSqlDouble(int ordinal, SqlDouble value)579         public virtual void SetSqlDouble(int ordinal, SqlDouble value)
580         {
581             EnsureSubclassOverride();
582             ValueUtilsSmi.SetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
583         }
584 
SetSqlMoney(int ordinal, SqlMoney value)585         public virtual void SetSqlMoney(int ordinal, SqlMoney value)
586         {
587             EnsureSubclassOverride();
588             ValueUtilsSmi.SetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
589         }
590 
SetSqlDateTime(int ordinal, SqlDateTime value)591         public virtual void SetSqlDateTime(int ordinal, SqlDateTime value)
592         {
593             EnsureSubclassOverride();
594             ValueUtilsSmi.SetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
595         }
596 
SetSqlXml(int ordinal, SqlXml value)597         public virtual void SetSqlXml(int ordinal, SqlXml value)
598         {
599             EnsureSubclassOverride();
600             ValueUtilsSmi.SetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
601         }
602 
SetSqlDecimal(int ordinal, SqlDecimal value)603         public virtual void SetSqlDecimal(int ordinal, SqlDecimal value)
604         {
605             EnsureSubclassOverride();
606             ValueUtilsSmi.SetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
607         }
608 
SetSqlString(int ordinal, SqlString value)609         public virtual void SetSqlString(int ordinal, SqlString value)
610         {
611             EnsureSubclassOverride();
612             ValueUtilsSmi.SetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
613         }
614 
SetSqlBinary(int ordinal, SqlBinary value)615         public virtual void SetSqlBinary(int ordinal, SqlBinary value)
616         {
617             EnsureSubclassOverride();
618             ValueUtilsSmi.SetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
619         }
620 
SetSqlGuid(int ordinal, SqlGuid value)621         public virtual void SetSqlGuid(int ordinal, SqlGuid value)
622         {
623             EnsureSubclassOverride();
624             ValueUtilsSmi.SetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
625         }
626 
SetSqlChars(int ordinal, SqlChars value)627         public virtual void SetSqlChars(int ordinal, SqlChars value)
628         {
629             EnsureSubclassOverride();
630             ValueUtilsSmi.SetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
631         }
632 
SetSqlBytes(int ordinal, SqlBytes value)633         public virtual void SetSqlBytes(int ordinal, SqlBytes value)
634         {
635             EnsureSubclassOverride();
636             ValueUtilsSmi.SetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value);
637         }
638 
639 
640         //
641         //  SqlDataRecord public API
642         //
643 
SqlDataRecord(params SqlMetaData[] metaData)644         public SqlDataRecord(params SqlMetaData[] metaData)
645         {
646             // Initial consistency check
647             if (null == metaData)
648             {
649                 throw ADP.ArgumentNull(nameof(metaData));
650             }
651 
652             _columnMetaData = new SqlMetaData[metaData.Length];
653             _columnSmiMetaData = new SmiExtendedMetaData[metaData.Length];
654             for (int i = 0; i < _columnSmiMetaData.Length; i++)
655             {
656                 if (null == metaData[i])
657                 {
658                     throw ADP.ArgumentNull($"{nameof(metaData)}[{i}]");
659                 }
660                 _columnMetaData[i] = metaData[i];
661                 _columnSmiMetaData[i] = MetaDataUtilsSmi.SqlMetaDataToSmiExtendedMetaData(_columnMetaData[i]);
662             }
663 
664             _eventSink = new SmiEventSink_Default();
665 
666             _recordBuffer = new MemoryRecordBuffer(_columnSmiMetaData);
667             _usesStringStorageForXml = true;
668             _eventSink.ProcessMessagesAndThrow();
669         }
670 
SqlDataRecord(SmiRecordBuffer recordBuffer, params SmiExtendedMetaData[] metaData)671         internal SqlDataRecord(SmiRecordBuffer recordBuffer, params SmiExtendedMetaData[] metaData)
672         {
673             Debug.Assert(null != recordBuffer, "invalid attempt to instantiate SqlDataRecord with null SmiRecordBuffer");
674             Debug.Assert(null != metaData, "invalid attempt to instantiate SqlDataRecord with null SmiExtendedMetaData[]");
675 
676             _columnMetaData = new SqlMetaData[metaData.Length];
677             _columnSmiMetaData = new SmiExtendedMetaData[metaData.Length];
678             for (int i = 0; i < _columnSmiMetaData.Length; i++)
679             {
680                 _columnSmiMetaData[i] = metaData[i];
681                 _columnMetaData[i] = MetaDataUtilsSmi.SmiExtendedMetaDataToSqlMetaData(_columnSmiMetaData[i]);
682             }
683 
684             _eventSink = new SmiEventSink_Default();
685 
686             _recordBuffer = recordBuffer;
687             _eventSink.ProcessMessagesAndThrow();
688         }
689 
690         //
691         //  SqlDataRecord private members
692         //
693         internal SmiRecordBuffer RecordBuffer
694         {  // used by SqlPipe
695             get
696             {
697                 return _recordBuffer;
698             }
699         }
700 
701 
InternalGetMetaData()702         internal SqlMetaData[] InternalGetMetaData()
703         {
704             return _columnMetaData;
705         }
706 
InternalGetSmiMetaData()707         internal SmiExtendedMetaData[] InternalGetSmiMetaData()
708         {
709             return _columnSmiMetaData;
710         }
711 
GetSmiMetaData(int ordinal)712         internal SmiExtendedMetaData GetSmiMetaData(int ordinal)
713         {
714             return _columnSmiMetaData[ordinal];
715         }
716 
ThrowIfInvalidOrdinal(int ordinal)717         internal void ThrowIfInvalidOrdinal(int ordinal)
718         {
719             if (0 > ordinal || FieldCount <= ordinal)
720             {
721                 throw ADP.IndexOutOfRange(ordinal);
722             }
723         }
EnsureSubclassOverride()724         private void EnsureSubclassOverride()
725         {
726             if (null == _recordBuffer)
727             {
728                 throw SQL.SubclassMustOverride();
729             }
730         }
731 
System.Data.IDataRecord.GetData(int ordinal)732         IDataReader System.Data.IDataRecord.GetData (int ordinal)
733         {
734             throw ADP.NotSupported();
735         }
736     }
737 }
738 
739