private void CreateIndex()
{
if (_index == null)
{
if (_nCandidates == 0)
{
_index = new Index(_table, _indexFields, _recordStates, null);
_index.AddRef();
}
else
{
int i;
int lenCanColumns = _candidateColumns.Length;
int lenIndexDesc = _indexFields.Length;
bool equalsOperator = true;
for (i = 0; i < lenCanColumns; i++)
{
if (_candidateColumns[i] != null)
{
if (!_candidateColumns[i].equalsOperator)
{
equalsOperator = false;
break;
}
}
}
int j = 0;
for (i = 0; i < lenIndexDesc; i++)
{
ColumnInfo candidateColumn = _candidateColumns[_indexFields[i].Column.Ordinal];
if (candidateColumn != null)
{
candidateColumn.flag = true;
j++;
}
}
int indexNotInCandidates = lenIndexDesc - j;
int candidatesNotInIndex = _nCandidates - j;
IndexField[] ndxFields = new IndexField[_nCandidates + indexNotInCandidates];
if (equalsOperator)
{
j = 0;
for (i = 0; i < lenCanColumns; i++)
{
if (_candidateColumns[i] != null)
{
ndxFields[j++] = new IndexField(_table.Columns[i], isDescending: false);
_candidateColumns[i].flag = false;// this means it is processed
}
}
for (i = 0; i < lenIndexDesc; i++)
{
ColumnInfo canColumn = _candidateColumns[_indexFields[i].Column.Ordinal];
if (canColumn == null || canColumn.flag)
{ // if sort column is not a filter col , or not processed
ndxFields[j++] = _indexFields[i];
if (canColumn != null)
{
canColumn.flag = false;
}
}
}
for (i = 0; i < _candidateColumns.Length; i++)
{
if (_candidateColumns[i] != null)
{
_candidateColumns[i].flag = false;// same as before, it is false when it returns
}
}
// Debug.Assert(j == candidatesNotInIndex, "Whole ndxDesc should be filled!");
_index = new Index(_table, ndxFields, _recordStates, null);
if (!IsOperatorIn(_expression))
{
// if the expression contains an 'IN' operator, the index will not be shared
// therefore we do not need to index.AddRef, also table would track index consuming more memory until first write
_index.AddRef();
}
_matchedCandidates = _nCandidates;
}
else
{
for (i = 0; i < lenIndexDesc; i++)
{
ndxFields[i] = _indexFields[i];
ColumnInfo canColumn = _candidateColumns[_indexFields[i].Column.Ordinal];
if (canColumn != null)
canColumn.flag = true;
}
j = i;
for (i = 0; i < lenCanColumns; i++)
{
if (_candidateColumns[i] != null)
{
if (!_candidateColumns[i].flag)
{
ndxFields[j++] = new IndexField(_table.Columns[i], isDescending: false);
}
else
{
_candidateColumns[i].flag = false;
}
}
}
// Debug.Assert(j == nCandidates+indexNotInCandidates, "Whole ndxDesc should be filled!");
_index = new Index(_table, ndxFields, _recordStates, null);
_matchedCandidates = 0;
if (_linearExpression != _expression)
{
IndexField[] fields = _index._indexFields;
while (_matchedCandidates < j)
{
ColumnInfo canColumn = _candidateColumns[fields[_matchedCandidates].Column.Ordinal];
if (canColumn == null || canColumn.expr == null)
break;
_matchedCandidates++;
if (!canColumn.equalsOperator)
break;
}
}
for (i = 0; i < _candidateColumns.Length; i++)
{
if (_candidateColumns[i] != null)
{
_candidateColumns[i].flag = false;// same as before, it is false when it returns
}
}
}
}
}
}