Skip to content

Commit a4974d4

Browse files
authored
Port lazy initialize hidden column map to netfx (#1443)
1 parent 0eeb135 commit a4974d4

3 files changed

Lines changed: 102 additions & 67 deletions

File tree

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDataReader.cs

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData()
329329

330330
if (null != metaData && 0 < metaData.Length)
331331
{
332-
metaDataReturn = new SmiExtendedMetaData[metaData.visibleColumns];
333-
332+
metaDataReturn = new SmiExtendedMetaData[metaData.VisibleColumnCount];
333+
int returnIndex = 0;
334334
for (int index = 0; index < metaData.Length; index++)
335335
{
336336
_SqlMetaData colMetaData = metaData[index];
@@ -369,7 +369,7 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData()
369369
length /= ADP.CharSize;
370370
}
371371

372-
metaDataReturn[index] = new SmiQueryMetaData(
372+
metaDataReturn[returnIndex] = new SmiQueryMetaData(
373373
colMetaData.type,
374374
length,
375375
colMetaData.precision,
@@ -397,6 +397,7 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData()
397397
colMetaData.IsDifferentName,
398398
colMetaData.IsHidden
399399
);
400+
returnIndex += 1;
400401
}
401402
}
402403
}
@@ -458,7 +459,7 @@ override public int VisibleFieldCount
458459
{
459460
return 0;
460461
}
461-
return (md.visibleColumns);
462+
return md.VisibleColumnCount;
462463
}
463464
}
464465

@@ -1352,31 +1353,6 @@ private bool TryConsumeMetaData()
13521353
Debug.Assert(!ignored, "Parser read a row token while trying to read metadata");
13531354
}
13541355

1355-
// we hide hidden columns from the user so build an internal map
1356-
// that compacts all hidden columns from the array
1357-
if (null != _metaData)
1358-
{
1359-
1360-
if (_snapshot != null && object.ReferenceEquals(_snapshot._metadata, _metaData))
1361-
{
1362-
_metaData = (_SqlMetaDataSet)_metaData.Clone();
1363-
}
1364-
1365-
_metaData.visibleColumns = 0;
1366-
1367-
Debug.Assert(null == _metaData.indexMap, "non-null metaData indexmap");
1368-
int[] indexMap = new int[_metaData.Length];
1369-
for (int i = 0; i < indexMap.Length; ++i)
1370-
{
1371-
indexMap[i] = _metaData.visibleColumns;
1372-
1373-
if (!(_metaData[i].IsHidden))
1374-
{
1375-
_metaData.visibleColumns++;
1376-
}
1377-
}
1378-
_metaData.indexMap = indexMap;
1379-
}
13801356

13811357
return true;
13821358
}
@@ -1690,15 +1666,15 @@ override public DataTable GetSchemaTable()
16901666
try
16911667
{
16921668
statistics = SqlStatistics.StartTimer(Statistics);
1693-
if (null == _metaData || null == _metaData.schemaTable)
1669+
if (null == _metaData || null == _metaData._schemaTable)
16941670
{
16951671
if (null != this.MetaData)
16961672
{
1697-
_metaData.schemaTable = BuildSchemaTable();
1698-
Debug.Assert(null != _metaData.schemaTable, "No schema information yet!");
1673+
_metaData._schemaTable = BuildSchemaTable();
1674+
Debug.Assert(null != _metaData._schemaTable, "No schema information yet!");
16991675
}
17001676
}
1701-
return _metaData?.schemaTable;
1677+
return _metaData?._schemaTable;
17021678
}
17031679
finally
17041680
{
@@ -2994,11 +2970,11 @@ virtual public int GetSqlValues(object[] values)
29942970

29952971
SetTimeout(_defaultTimeoutMilliseconds);
29962972

2997-
int copyLen = (values.Length < _metaData.visibleColumns) ? values.Length : _metaData.visibleColumns;
2973+
int copyLen = (values.Length < _metaData.VisibleColumnCount) ? values.Length : _metaData.VisibleColumnCount;
29982974

29992975
for (int i = 0; i < copyLen; i++)
30002976
{
3001-
values[_metaData.indexMap[i]] = GetSqlValueInternal(i);
2977+
values[_metaData.GetVisibleColumnIndex(i)] = GetSqlValueInternal(i);
30022978
}
30032979
return copyLen;
30042980
}
@@ -3398,7 +3374,7 @@ override public int GetValues(object[] values)
33983374

33993375
CheckMetaDataIsReady();
34003376

3401-
int copyLen = (values.Length < _metaData.visibleColumns) ? values.Length : _metaData.visibleColumns;
3377+
int copyLen = (values.Length < _metaData.VisibleColumnCount) ? values.Length : _metaData.VisibleColumnCount;
34023378
int maximumColumn = copyLen - 1;
34033379

34043380
SetTimeout(_defaultTimeoutMilliseconds);
@@ -3414,12 +3390,19 @@ override public int GetValues(object[] values)
34143390
for (int i = 0; i < copyLen; i++)
34153391
{
34163392
// Get the usable, TypeSystem-compatible value from the iternal buffer
3417-
values[_metaData.indexMap[i]] = GetValueFromSqlBufferInternal(_data[i], _metaData[i]);
3393+
int fieldIndex = _metaData.GetVisibleColumnIndex(i);
3394+
values[i] = GetValueFromSqlBufferInternal(_data[fieldIndex], _metaData[fieldIndex]);
34183395

34193396
// If this is sequential access, then we need to wipe the internal buffer
34203397
if ((sequentialAccess) && (i < maximumColumn))
34213398
{
34223399
_data[i].Clear();
3400+
if (fieldIndex > i && fieldIndex > 0)
3401+
{
3402+
// if we jumped an index forward because of a hidden column see if the buffer before the
3403+
// current one was populated by the seek forward and clear it if it was
3404+
_data[fieldIndex - 1].Clear();
3405+
}
34233406
}
34243407
}
34253408

@@ -4767,7 +4750,7 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo)
47674750
_tableNames = null;
47684751
if (_metaData != null)
47694752
{
4770-
_metaData.schemaTable = null;
4753+
_metaData._schemaTable = null;
47714754
_data = SqlBuffer.CreateBufferArray(metaData.Length);
47724755
}
47734756

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5094,7 +5094,6 @@ internal bool TryProcessAltMetaData(int cColumns, TdsParserStateObject stateObj,
50945094

50955095
metaData = null;
50965096
_SqlMetaDataSet altMetaDataSet = new _SqlMetaDataSet(cColumns, null);
5097-
int[] indexMap = new int[cColumns];
50985097

50995098
if (!stateObj.TryReadUInt16(out altMetaDataSet.id))
51005099
{
@@ -5191,12 +5190,8 @@ internal bool TryProcessAltMetaData(int cColumns, TdsParserStateObject stateObj,
51915190
break;
51925191
}
51935192
}
5194-
indexMap[i] = i;
51955193
}
51965194

5197-
altMetaDataSet.indexMap = indexMap;
5198-
altMetaDataSet.visibleColumns = cColumns;
5199-
52005195
metaData = altMetaDataSet;
52015196
return true;
52025197
}

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserHelperClasses.cs

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -511,73 +511,130 @@ public object Clone()
511511
}
512512
}
513513

514-
sealed internal class _SqlMetaDataSet : ICloneable
514+
sealed internal class _SqlMetaDataSet
515515
{
516516
internal ushort id; // for altrow-columns only
517-
internal int[] indexMap;
518-
internal int visibleColumns;
519-
internal DataTable schemaTable;
517+
internal DataTable _schemaTable;
520518
internal readonly SqlTceCipherInfoTable cekTable; // table of "column encryption keys" used for this metadataset
521-
internal readonly _SqlMetaData[] metaDataArray;
519+
internal readonly _SqlMetaData[] _metaDataArray;
520+
private int _hiddenColumnCount;
521+
private int[] _visibleColumnMap;
522522

523523
internal _SqlMetaDataSet(int count, SqlTceCipherInfoTable cipherTable)
524524
{
525+
_hiddenColumnCount = -1;
525526
cekTable = cipherTable;
526-
metaDataArray = new _SqlMetaData[count];
527-
for (int i = 0; i < metaDataArray.Length; ++i)
527+
_metaDataArray = new _SqlMetaData[count];
528+
for (int i = 0; i < _metaDataArray.Length; ++i)
528529
{
529-
metaDataArray[i] = new _SqlMetaData(i);
530+
_metaDataArray[i] = new _SqlMetaData(i);
530531
}
531532
}
532533

533534
private _SqlMetaDataSet(_SqlMetaDataSet original)
534535
{
535-
this.id = original.id;
536-
// although indexMap is not immutable, in practice it is initialized once and then passed around
537-
this.indexMap = original.indexMap;
538-
this.visibleColumns = original.visibleColumns;
539-
this.schemaTable = original.schemaTable;
540-
if (original.metaDataArray == null)
536+
id = original.id;
537+
_hiddenColumnCount = original._hiddenColumnCount;
538+
_visibleColumnMap = original._visibleColumnMap;
539+
_schemaTable = original._schemaTable;
540+
if (original._metaDataArray == null)
541541
{
542-
metaDataArray = null;
542+
_metaDataArray = null;
543543
}
544544
else
545545
{
546-
metaDataArray = new _SqlMetaData[original.metaDataArray.Length];
547-
for (int idx = 0; idx < metaDataArray.Length; idx++)
546+
_metaDataArray = new _SqlMetaData[original._metaDataArray.Length];
547+
for (int idx = 0; idx < _metaDataArray.Length; idx++)
548548
{
549-
metaDataArray[idx] = (_SqlMetaData)original.metaDataArray[idx].Clone();
549+
_metaDataArray[idx] = (_SqlMetaData)original._metaDataArray[idx].Clone();
550550
}
551551
}
552552
}
553553

554+
internal int VisibleColumnCount
555+
{
556+
get
557+
{
558+
if (_hiddenColumnCount == -1)
559+
{
560+
SetupHiddenColumns();
561+
}
562+
return Length - _hiddenColumnCount;
563+
}
564+
}
565+
554566
internal int Length
555567
{
556568
get
557569
{
558-
return metaDataArray.Length;
570+
return _metaDataArray.Length;
559571
}
560572
}
561573

562574
internal _SqlMetaData this[int index]
563575
{
564576
get
565577
{
566-
return metaDataArray[index];
578+
return _metaDataArray[index];
567579
}
568580
set
569581
{
570582
Debug.Assert(null == value, "used only by SqlBulkCopy");
571-
metaDataArray[index] = value;
583+
_metaDataArray[index] = value;
572584
}
573585
}
574586

575-
public object Clone()
587+
public int GetVisibleColumnIndex(int index)
588+
{
589+
if (_hiddenColumnCount == -1)
590+
{
591+
SetupHiddenColumns();
592+
}
593+
if (_visibleColumnMap is null)
594+
{
595+
return index;
596+
}
597+
else
598+
{
599+
return _visibleColumnMap[index];
600+
}
601+
}
602+
603+
public _SqlMetaDataSet Clone()
576604
{
577605
return new _SqlMetaDataSet(this);
578606
}
607+
608+
private void SetupHiddenColumns()
609+
{
610+
int hiddenColumnCount = 0;
611+
for (int index = 0; index < Length; index++)
612+
{
613+
if (_metaDataArray[index].IsHidden)
614+
{
615+
hiddenColumnCount += 1;
616+
}
617+
}
618+
619+
if (hiddenColumnCount > 0)
620+
{
621+
int[] visibleColumnMap = new int[Length - hiddenColumnCount];
622+
int mapIndex = 0;
623+
for (int metaDataIndex = 0; metaDataIndex < Length; metaDataIndex++)
624+
{
625+
if (!_metaDataArray[metaDataIndex].IsHidden)
626+
{
627+
visibleColumnMap[mapIndex] = metaDataIndex;
628+
mapIndex += 1;
629+
}
630+
}
631+
_visibleColumnMap = visibleColumnMap;
632+
}
633+
_hiddenColumnCount = hiddenColumnCount;
634+
}
579635
}
580636

637+
581638
sealed internal class _SqlMetaDataSetCollection : ICloneable
582639
{
583640
private readonly List<_SqlMetaDataSet> altMetaDataSetArray;
@@ -622,10 +679,10 @@ internal _SqlMetaDataSet GetAltMetaData(int id)
622679
public object Clone()
623680
{
624681
_SqlMetaDataSetCollection result = new _SqlMetaDataSetCollection();
625-
result.metaDataSet = metaDataSet == null ? null : (_SqlMetaDataSet)metaDataSet.Clone();
682+
result.metaDataSet = metaDataSet == null ? null : metaDataSet.Clone();
626683
foreach (_SqlMetaDataSet set in altMetaDataSetArray)
627684
{
628-
result.altMetaDataSetArray.Add((_SqlMetaDataSet)set.Clone());
685+
result.altMetaDataSetArray.Add(set.Clone());
629686
}
630687
return result;
631688
}

0 commit comments

Comments
 (0)