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

Clustered index #8

Merged
merged 7 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 48 additions & 0 deletions DataStructures/BTreeCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,54 @@ public BTreeCollection(IAllocateMixedPage pageAllocator, ColumnInfo[] columnType
this.projectionRemoveIndexCol = new ProjectExtendInfo(mps, prjs, new ColumnInfo[0]);
}

public BTreeCollection(IAllocateMixedPage pageAllocator, ColumnInfo[] columnTypes, Func<RowHolder, RowHolder, int> indexComparer, int indexPosition, ulong initialPageId, ITransaction tran)
{
if (pageAllocator == null || columnTypes == null || columnTypes.Length == 0 || tran == null)
{
throw new ArgumentNullException();
}

this.pageAllocator = pageAllocator;
this.columnTypes = columnTypes;
this.indexPosition = indexPosition;

// Add PagePointer to the end of each row.
// Page pointer will be used as pointer in btree.
// Prev page pointer will point to the left side of the first key.
// Next page pointer is used to encode additional info.
// For now next page is used to encode whether the page is leaf.
this.btreeColumnTypes = new ColumnInfo[columnTypes.Length + 1];
Array.Copy(columnTypes, this.btreeColumnTypes, columnTypes.Length);
this.btreeColumnTypes[columnTypes.Length] = new ColumnInfo(ColumnType.PagePointer);
this.collectionRootPageId = initialPageId;

using Releaser lck = tran.AcquireLock(initialPageId, LockManager.LockTypeEnum.Shared).ConfigureAwait(false).GetAwaiter().GetResult();
MixedPage rootPage = pageAllocator.GetMixedPage(this.collectionRootPageId, tran, columnTypes).Result;
uint maxRowCount = rootPage.MaxRowCount();

// In btree we can fit max 2*t + 1 elements.
// If we can fit even number we will keep the space unused.
this.maxElemsPerPage = (int)maxRowCount;
if (maxRowCount % 2 == 0)
{
this.maxElemsPerPage--;
}

this.indexComparer = indexComparer;

this.pagePointerRowPosition = this.columnTypes.Length;

MappingType[] mps = new MappingType[columnTypes.Length];
int[] prjs = new int[columnTypes.Length];
for (int i = 0; i < prjs.Length; i++)
{
mps[i] = MappingType.Projection;
prjs[i] = i;
}

this.projectionRemoveIndexCol = new ProjectExtendInfo(mps, prjs, new ColumnInfo[0]);
}

public async Task Add(RowHolder item, ITransaction tran)
{
// Extend RowHolder with page pointer.
Expand Down
33 changes: 33 additions & 0 deletions DataStructures/PageListCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,39 @@

namespace DataStructures
{
public enum CollectionType
{
PageList,
BTree,
}

public static class CollectionHandler
{
public static async Task<MixedPage> CreateInitialPage(CollectionType collectionType, ColumnInfo[] columnInfos, IAllocateMixedPage pageAllocator, ITransaction tran)
{
ArgumentNullException.ThrowIfNull(collectionType);
ArgumentNullException.ThrowIfNull(pageAllocator);
ArgumentNullException.ThrowIfNull(tran);

if (collectionType == CollectionType.PageList)
{
return await pageAllocator.AllocateMixedPage(columnInfos, PageManagerConstants.NullPageId, PageManagerConstants.NullPageId, tran);
}
else if (collectionType == CollectionType.BTree)
{
// Need to extend it to add page pointers.
ColumnInfo[] btreeColumnTypes = new ColumnInfo[columnInfos.Length + 1];
Array.Copy(columnInfos, btreeColumnTypes, columnInfos.Length);
btreeColumnTypes[columnInfos.Length] = new ColumnInfo(ColumnType.PagePointer);
return await pageAllocator.AllocateMixedPage(btreeColumnTypes, PageManagerConstants.NullPageId, PageManagerConstants.NullPageId, tran);
}
else
{
throw new ArgumentException();
}
}
}

public interface IPageCollection<T>
{
Task<ulong> Count(ITransaction tran);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;

namespace MetadataManager.Exceptions
{
public class OnlyOneClusteredIndexSupportedException : Exception
{
}
}
38 changes: 27 additions & 11 deletions MetadataManager/MetadataColumns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,32 @@ namespace MetadataManager
{
public struct MetadataColumn
{
public const int NotPartOfClusteredIndex = -1;

public const int ColumnIdColumnPos = 0;
public readonly int ColumnId;
public const int TableIdColumnPos = 1;
public readonly int TableId;
public const int ColumnNameColumnPos = 2;
public readonly string ColumnName;
public const int ColumnTypeColumnPos = 3;
public const int ColumnTypeLength = 4;
public readonly ColumnInfo ColumnType;
public const int ColumnTypeLength = 4;
public const int ClusteredIndexPartPos = 5;
public readonly int ClusteredIndexPart;

public MetadataColumn(int columnId, int tableId, string columnName, ColumnInfo columnInfo)
public MetadataColumn(int columnId, int tableId, string columnName, ColumnInfo columnInfo, int clusteredIndexPart = NotPartOfClusteredIndex)
{
this.ColumnId = columnId;
this.TableId = tableId;
this.ColumnName = columnName;
this.ColumnType = columnInfo;
this.ClusteredIndexPart = clusteredIndexPart;
}

public MetadataColumn SetNewColumnPosition(int columnId)
{
return new MetadataColumn(columnId, this.TableId, this.ColumnName, this.ColumnType);
return new MetadataColumn(columnId, this.TableId, this.ColumnName, this.ColumnType, this.ClusteredIndexPart);
}
}

Expand All @@ -38,12 +43,13 @@ public MetadataColumn SetNewColumnPosition(int columnId)
/// </summary>
public struct ColumnCreateDefinition
{
public ColumnCreateDefinition(int tableId, string columnName, ColumnInfo columnInfo, int columnId)
public ColumnCreateDefinition(int tableId, string columnName, ColumnInfo columnInfo, int columnId, int clusteredIndexPosition)
{
this.TableId = tableId;
this.ColumnName = columnName;
this.ColumnType = columnInfo;
this.ColumnId = columnId;
this.ClusteredIndexPosition = clusteredIndexPosition;
}

/// <summary>
Expand All @@ -65,6 +71,12 @@ public ColumnCreateDefinition(int tableId, string columnName, ColumnInfo columnI
/// Column position in table.
/// </summary>
public int ColumnId { get; }

/// <summary>
/// Position in clustered index, if this column is part of it.
/// -1 otherwise.
/// </summary>
public int ClusteredIndexPosition { get; }
}

public class MetadataColumnsManager : IMetadataObjectManager<MetadataColumn, ColumnCreateDefinition, Tuple<int, int> /* column id - table id */>
Expand All @@ -83,6 +95,7 @@ public class MetadataColumnsManager : IMetadataObjectManager<MetadataColumn, Col
new ColumnInfo(ColumnType.String, MAX_NAME_LENGTH), // pointer to name
new ColumnInfo(ColumnType.Int), // column type
new ColumnInfo(ColumnType.Int), // column type length
new ColumnInfo(ColumnType.Int), // clustered index position.
};

public static ColumnInfo[] GetSchemaDefinition() => columnDefinitions;
Expand All @@ -109,7 +122,8 @@ await foreach (RowHolder rh in pageListCollection.Iterate(tran))
rh.GetField<int>(MetadataColumn.ColumnIdColumnPos),
rh.GetField<int>(MetadataColumn.TableIdColumnPos),
new string(columnName),
new ColumnInfo((ColumnType)rh.GetField<int>(MetadataColumn.ColumnTypeColumnPos), rh.GetField<int>(MetadataColumn.ColumnTypeLength)));
new ColumnInfo((ColumnType)rh.GetField<int>(MetadataColumn.ColumnTypeColumnPos), rh.GetField<int>(MetadataColumn.ColumnTypeLength)),
rh.GetField<int>(MetadataColumn.ClusteredIndexPartPos));
}
}

Expand All @@ -123,11 +137,12 @@ public async Task<int> CreateObject(ColumnCreateDefinition def, ITransaction tra
RowHolder rh = new RowHolder(columnDefinitions);
PagePointerOffsetPair namePointer = await this.stringHeap.Add(def.ColumnName.ToCharArray(), tran);

rh.SetField<int>(0, def.ColumnId);
rh.SetField<int>(1, def.TableId);
rh.SetField<PagePointerOffsetPair>(2, namePointer);
rh.SetField<int>(3, (int)def.ColumnType.ColumnType);
rh.SetField<int>(4, def.ColumnType.RepCount);
rh.SetField<int>(MetadataColumn.ColumnIdColumnPos, def.ColumnId);
rh.SetField<int>(MetadataColumn.TableIdColumnPos, def.TableId);
rh.SetField<PagePointerOffsetPair>(MetadataColumn.ColumnNameColumnPos, namePointer);
rh.SetField<int>(MetadataColumn.ColumnTypeColumnPos, (int)def.ColumnType.ColumnType);
rh.SetField<int>(MetadataColumn.ColumnTypeLength, def.ColumnType.RepCount);
rh.SetField<int>(MetadataColumn.ClusteredIndexPartPos, def.ClusteredIndexPosition);

await pageListCollection.Add(rh, tran);

Expand All @@ -144,7 +159,8 @@ await foreach (RowHolder rh in pageListCollection.Iterate(tran))
{
PagePointerOffsetPair stringPointer = rh.GetField<PagePointerOffsetPair>(MetadataColumn.ColumnNameColumnPos);

if (def.ColumnName == new string(await stringHeap.Fetch(stringPointer, tran)))
char[] strContent = await stringHeap.Fetch(stringPointer, tran);
if (CharrArray.Compare(strContent, def.ColumnName) == 0)
{
return true;
}
Expand Down
Loading