Skip to content

Commit

Permalink
Port lazy initialize hidden column map to netfx (#1443)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wraith2 authored Oct 5, 2022
1 parent 0eeb135 commit a4974d4
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData()

if (null != metaData && 0 < metaData.Length)
{
metaDataReturn = new SmiExtendedMetaData[metaData.visibleColumns];

metaDataReturn = new SmiExtendedMetaData[metaData.VisibleColumnCount];
int returnIndex = 0;
for (int index = 0; index < metaData.Length; index++)
{
_SqlMetaData colMetaData = metaData[index];
Expand Down Expand Up @@ -369,7 +369,7 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData()
length /= ADP.CharSize;
}

metaDataReturn[index] = new SmiQueryMetaData(
metaDataReturn[returnIndex] = new SmiQueryMetaData(
colMetaData.type,
length,
colMetaData.precision,
Expand Down Expand Up @@ -397,6 +397,7 @@ internal virtual SmiExtendedMetaData[] GetInternalSmiMetaData()
colMetaData.IsDifferentName,
colMetaData.IsHidden
);
returnIndex += 1;
}
}
}
Expand Down Expand Up @@ -458,7 +459,7 @@ override public int VisibleFieldCount
{
return 0;
}
return (md.visibleColumns);
return md.VisibleColumnCount;
}
}

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

// we hide hidden columns from the user so build an internal map
// that compacts all hidden columns from the array
if (null != _metaData)
{

if (_snapshot != null && object.ReferenceEquals(_snapshot._metadata, _metaData))
{
_metaData = (_SqlMetaDataSet)_metaData.Clone();
}

_metaData.visibleColumns = 0;

Debug.Assert(null == _metaData.indexMap, "non-null metaData indexmap");
int[] indexMap = new int[_metaData.Length];
for (int i = 0; i < indexMap.Length; ++i)
{
indexMap[i] = _metaData.visibleColumns;

if (!(_metaData[i].IsHidden))
{
_metaData.visibleColumns++;
}
}
_metaData.indexMap = indexMap;
}

return true;
}
Expand Down Expand Up @@ -1690,15 +1666,15 @@ override public DataTable GetSchemaTable()
try
{
statistics = SqlStatistics.StartTimer(Statistics);
if (null == _metaData || null == _metaData.schemaTable)
if (null == _metaData || null == _metaData._schemaTable)
{
if (null != this.MetaData)
{
_metaData.schemaTable = BuildSchemaTable();
Debug.Assert(null != _metaData.schemaTable, "No schema information yet!");
_metaData._schemaTable = BuildSchemaTable();
Debug.Assert(null != _metaData._schemaTable, "No schema information yet!");
}
}
return _metaData?.schemaTable;
return _metaData?._schemaTable;
}
finally
{
Expand Down Expand Up @@ -2994,11 +2970,11 @@ virtual public int GetSqlValues(object[] values)

SetTimeout(_defaultTimeoutMilliseconds);

int copyLen = (values.Length < _metaData.visibleColumns) ? values.Length : _metaData.visibleColumns;
int copyLen = (values.Length < _metaData.VisibleColumnCount) ? values.Length : _metaData.VisibleColumnCount;

for (int i = 0; i < copyLen; i++)
{
values[_metaData.indexMap[i]] = GetSqlValueInternal(i);
values[_metaData.GetVisibleColumnIndex(i)] = GetSqlValueInternal(i);
}
return copyLen;
}
Expand Down Expand Up @@ -3398,7 +3374,7 @@ override public int GetValues(object[] values)

CheckMetaDataIsReady();

int copyLen = (values.Length < _metaData.visibleColumns) ? values.Length : _metaData.visibleColumns;
int copyLen = (values.Length < _metaData.VisibleColumnCount) ? values.Length : _metaData.VisibleColumnCount;
int maximumColumn = copyLen - 1;

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

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

Expand Down Expand Up @@ -4767,7 +4750,7 @@ internal bool TrySetMetaData(_SqlMetaDataSet metaData, bool moreInfo)
_tableNames = null;
if (_metaData != null)
{
_metaData.schemaTable = null;
_metaData._schemaTable = null;
_data = SqlBuffer.CreateBufferArray(metaData.Length);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5094,7 +5094,6 @@ internal bool TryProcessAltMetaData(int cColumns, TdsParserStateObject stateObj,

metaData = null;
_SqlMetaDataSet altMetaDataSet = new _SqlMetaDataSet(cColumns, null);
int[] indexMap = new int[cColumns];

if (!stateObj.TryReadUInt16(out altMetaDataSet.id))
{
Expand Down Expand Up @@ -5191,12 +5190,8 @@ internal bool TryProcessAltMetaData(int cColumns, TdsParserStateObject stateObj,
break;
}
}
indexMap[i] = i;
}

altMetaDataSet.indexMap = indexMap;
altMetaDataSet.visibleColumns = cColumns;

metaData = altMetaDataSet;
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,73 +511,130 @@ public object Clone()
}
}

sealed internal class _SqlMetaDataSet : ICloneable
sealed internal class _SqlMetaDataSet
{
internal ushort id; // for altrow-columns only
internal int[] indexMap;
internal int visibleColumns;
internal DataTable schemaTable;
internal DataTable _schemaTable;
internal readonly SqlTceCipherInfoTable cekTable; // table of "column encryption keys" used for this metadataset
internal readonly _SqlMetaData[] metaDataArray;
internal readonly _SqlMetaData[] _metaDataArray;
private int _hiddenColumnCount;
private int[] _visibleColumnMap;

internal _SqlMetaDataSet(int count, SqlTceCipherInfoTable cipherTable)
{
_hiddenColumnCount = -1;
cekTable = cipherTable;
metaDataArray = new _SqlMetaData[count];
for (int i = 0; i < metaDataArray.Length; ++i)
_metaDataArray = new _SqlMetaData[count];
for (int i = 0; i < _metaDataArray.Length; ++i)
{
metaDataArray[i] = new _SqlMetaData(i);
_metaDataArray[i] = new _SqlMetaData(i);
}
}

private _SqlMetaDataSet(_SqlMetaDataSet original)
{
this.id = original.id;
// although indexMap is not immutable, in practice it is initialized once and then passed around
this.indexMap = original.indexMap;
this.visibleColumns = original.visibleColumns;
this.schemaTable = original.schemaTable;
if (original.metaDataArray == null)
id = original.id;
_hiddenColumnCount = original._hiddenColumnCount;
_visibleColumnMap = original._visibleColumnMap;
_schemaTable = original._schemaTable;
if (original._metaDataArray == null)
{
metaDataArray = null;
_metaDataArray = null;
}
else
{
metaDataArray = new _SqlMetaData[original.metaDataArray.Length];
for (int idx = 0; idx < metaDataArray.Length; idx++)
_metaDataArray = new _SqlMetaData[original._metaDataArray.Length];
for (int idx = 0; idx < _metaDataArray.Length; idx++)
{
metaDataArray[idx] = (_SqlMetaData)original.metaDataArray[idx].Clone();
_metaDataArray[idx] = (_SqlMetaData)original._metaDataArray[idx].Clone();
}
}
}

internal int VisibleColumnCount
{
get
{
if (_hiddenColumnCount == -1)
{
SetupHiddenColumns();
}
return Length - _hiddenColumnCount;
}
}

internal int Length
{
get
{
return metaDataArray.Length;
return _metaDataArray.Length;
}
}

internal _SqlMetaData this[int index]
{
get
{
return metaDataArray[index];
return _metaDataArray[index];
}
set
{
Debug.Assert(null == value, "used only by SqlBulkCopy");
metaDataArray[index] = value;
_metaDataArray[index] = value;
}
}

public object Clone()
public int GetVisibleColumnIndex(int index)
{
if (_hiddenColumnCount == -1)
{
SetupHiddenColumns();
}
if (_visibleColumnMap is null)
{
return index;
}
else
{
return _visibleColumnMap[index];
}
}

public _SqlMetaDataSet Clone()
{
return new _SqlMetaDataSet(this);
}

private void SetupHiddenColumns()
{
int hiddenColumnCount = 0;
for (int index = 0; index < Length; index++)
{
if (_metaDataArray[index].IsHidden)
{
hiddenColumnCount += 1;
}
}

if (hiddenColumnCount > 0)
{
int[] visibleColumnMap = new int[Length - hiddenColumnCount];
int mapIndex = 0;
for (int metaDataIndex = 0; metaDataIndex < Length; metaDataIndex++)
{
if (!_metaDataArray[metaDataIndex].IsHidden)
{
visibleColumnMap[mapIndex] = metaDataIndex;
mapIndex += 1;
}
}
_visibleColumnMap = visibleColumnMap;
}
_hiddenColumnCount = hiddenColumnCount;
}
}


sealed internal class _SqlMetaDataSetCollection : ICloneable
{
private readonly List<_SqlMetaDataSet> altMetaDataSetArray;
Expand Down Expand Up @@ -622,10 +679,10 @@ internal _SqlMetaDataSet GetAltMetaData(int id)
public object Clone()
{
_SqlMetaDataSetCollection result = new _SqlMetaDataSetCollection();
result.metaDataSet = metaDataSet == null ? null : (_SqlMetaDataSet)metaDataSet.Clone();
result.metaDataSet = metaDataSet == null ? null : metaDataSet.Clone();
foreach (_SqlMetaDataSet set in altMetaDataSetArray)
{
result.altMetaDataSetArray.Add((_SqlMetaDataSet)set.Clone());
result.altMetaDataSetArray.Add(set.Clone());
}
return result;
}
Expand Down

0 comments on commit a4974d4

Please sign in to comment.