Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port lazy initialize hidden column map to netfx #1443

Merged
merged 3 commits into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
DavoudEshtehari marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly List<_SqlMetaDataSet> altMetaDataSetArray;
Expand Down