Skip to content

Commit dab6fc8

Browse files
committed
Refactor
1 parent c14a6a4 commit dab6fc8

File tree

16 files changed

+415
-384
lines changed

16 files changed

+415
-384
lines changed
Lines changed: 34 additions & 230 deletions
Original file line numberDiff line numberDiff line change
@@ -1,263 +1,67 @@
1+
12
using System.Collections.Generic;
2-
using MiniSQL.Library.Models;
3+
using System.IO;
4+
using MiniSQL.BufferManager.Controllers;
35
using MiniSQL.Library.Interfaces;
4-
using System;
5-
using System.Linq;
6+
using MiniSQL.Library.Models;
67

78
namespace MiniSQL.Api.Controllers
89
{
910
public class ApiController : IApi
1011
{
12+
private readonly DatabaseBuilder _builder;
1113

12-
private readonly IInterpreter _interpreter;
13-
private readonly ICatalogManager _catalogManager;
14-
private readonly IRecordManager _recordManager;
15-
16-
public ApiController(IInterpreter interpreter, ICatalogManager catalogManager, IRecordManager recordManager)
17-
{
18-
_catalogManager = catalogManager;
19-
_interpreter = interpreter;
20-
_recordManager = recordManager;
21-
}
14+
private IDatabaseController _database;
15+
private Pager _pager;
2216

23-
public List<SelectResult> Query(string sql)
24-
{
25-
List<SelectResult> selectResults = new List<SelectResult>();
26-
Query query;
27-
try
28-
{
29-
query = Parse(sql);
30-
}
31-
catch (Exception ex)
32-
{
33-
throw new StatementPreCheckException(ex.Message, ex.InnerException);
34-
}
35-
foreach (IStatement statement in query.StatementList)
36-
{
37-
SelectResult selectResult = HandleStatement(statement);
38-
if (selectResult != null)
39-
{
40-
selectResults.Add(selectResult);
41-
}
42-
}
43-
return selectResults;
44-
}
17+
public bool IsUsingDatabase { get; private set; } = false;
18+
private string _nameOfDatabaseInUse;
4519

46-
private SelectResult HandleStatement(IStatement statement)
20+
public ApiController(DatabaseBuilder builder)
4721
{
48-
SelectResult selectResult = null;
49-
switch (statement.Type)
50-
{
51-
case StatementType.CreateStatement:
52-
HandleStatement((CreateStatement)statement);
53-
break;
54-
case StatementType.DropStatement:
55-
HandleStatement((DropStatement)statement);
56-
break;
57-
case StatementType.DeleteStatement:
58-
HandleStatement((DeleteStatement)statement);
59-
break;
60-
case StatementType.InsertStatement:
61-
HandleStatement((InsertStatement)statement);
62-
break;
63-
case StatementType.SelectStatement:
64-
selectResult = HandleSelectStatement((SelectStatement)statement);
65-
break;
66-
case StatementType.ShowStatement:
67-
selectResult = HandleSelectStatement((ShowStatement)statement);
68-
break;
69-
case StatementType.ExecFileStatement:
70-
throw new Exception("Impossible reach");
71-
}
72-
return selectResult;
73-
}
74-
75-
// create statement
76-
private void HandleStatement(CreateStatement statement)
77-
{
78-
_catalogManager.CheckValidation(statement);
79-
switch (statement.CreateType)
80-
{
81-
case CreateType.Table:
82-
int newTableRoot = _recordManager.CreateTable();
83-
_catalogManager.CreateStatement(statement, newTableRoot);
84-
break;
85-
case CreateType.Index:
86-
SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName);
87-
int newIndexRoot = _recordManager.CreateIndex(tableSchema.RootPage, statement.AttributeName, tableSchema.SQL.AttributeDeclarations);
88-
_catalogManager.CreateStatement(statement, newIndexRoot);
89-
break;
90-
}
22+
_builder = builder;
9123
}
9224

93-
// drop statement
94-
private void HandleStatement(DropStatement statement)
25+
// use database
26+
public void ChangeContext(string newDatabaseName)
9527
{
96-
_catalogManager.CheckValidation(statement);
97-
SchemaRecord schema;
98-
switch (statement.TargetType)
28+
if (IsUsingDatabase)
9929
{
100-
case DropTarget.Table:
101-
schema = _catalogManager.GetTableSchemaRecord(statement.TableName);
102-
List<SchemaRecord> indices = _catalogManager.GetIndicesSchemaRecord(statement.TableName);
103-
// drop table
104-
_catalogManager.DropStatement(statement);
105-
_recordManager.DropTable(schema.RootPage);
106-
// drop index trees
107-
foreach (SchemaRecord index in indices)
108-
{
109-
_recordManager.DropTable(index.RootPage);
110-
}
111-
break;
112-
case DropTarget.Index:
113-
schema = _catalogManager.GetIndexSchemaRecord(statement.IndexName);
114-
_catalogManager.DropStatement(statement);
115-
_recordManager.DropTable(schema.RootPage);
116-
break;
30+
_pager.Close();
11731
}
32+
// init
33+
this.IsUsingDatabase = true;
34+
this._nameOfDatabaseInUse = newDatabaseName;
35+
(_database, _pager) = _builder.UseDatabase(newDatabaseName);
11836
}
11937

120-
// delete statement
121-
// NOTICE: relative index trees will NOT change accordingly
122-
private void HandleStatement(DeleteStatement statement)
123-
{
124-
// get table and indices
125-
_catalogManager.CheckValidation(statement);
126-
SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName);
127-
List<SchemaRecord> indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName);
128-
129-
// TODO
130-
// delete index records from index trees
131-
// __problem__:
132-
// attribute names := (priKey, a, b, c)
133-
// condition := b < 3 and c > 5
134-
// fun facts: b and c both have index trees
135-
// issue: to delete the records satisfying the condition above
136-
137-
// delete record from table tree
138-
int newTableRootPage = _recordManager.DeleteRecords(statement.Condition, tableSchema.SQL.PrimaryKey, tableSchema.SQL.AttributeDeclarations, tableSchema.RootPage);
139-
_catalogManager.TryUpdateSchemaRecord(statement.TableName, newTableRootPage);
140-
}
141-
142-
private SelectResult HandleSelectStatement(ShowStatement statement)
38+
// delete database file
39+
public void DropDatabase(string databaseName)
14340
{
144-
List<SchemaRecord> tableSchemas = _catalogManager.GetTablesSchemaRecord();
145-
SelectResult result = new SelectResult();
146-
result.ColumnDeclarations = new List<AttributeDeclaration>() { new AttributeDeclaration() {AttributeName = "Table", Type = AttributeTypes.Char, CharLimit = 80}};
147-
result.Rows = new List<List<AtomValue>>();
148-
foreach (SchemaRecord tableSchema in tableSchemas)
41+
if (_nameOfDatabaseInUse == databaseName)
14942
{
150-
List<AtomValue> row = new List<AtomValue>();
151-
AtomValue col = new AtomValue();
152-
col.Type = AttributeTypes.Char;
153-
col.CharLimit = 80;
154-
col.StringValue = tableSchema.Name;
155-
row.Add(col);
156-
result.Rows.Add(row);
43+
_pager.Close();
44+
IsUsingDatabase = false;
15745
}
158-
return result;
46+
File.Delete($"{databaseName}.minidb");
47+
File.Delete($"{databaseName}.indices.dbcatalog");
48+
File.Delete($"{databaseName}.tables.dbcatalog");
15949
}
16050

161-
private SelectResult HandleSelectStatement(SelectStatement statement)
51+
public void ClosePager()
16252
{
163-
bool isIndexTreeAvailable = false;
164-
// get table and indices
165-
_catalogManager.CheckValidation(statement);
166-
SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.FromTable);
167-
List<SchemaRecord> indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.FromTable);
168-
169-
// select from index tree if possible
170-
AtomValue primaryKey = null;
171-
if (statement.Condition != null)
172-
{
173-
foreach (SchemaRecord indexSchema in indexSchemas)
174-
{
175-
// if there has a condition `=` on indexed column
176-
if (statement.Condition.Ands.ContainsKey(indexSchema.SQL.AttributeName)
177-
&& statement.Condition.Ands[indexSchema.SQL.AttributeName].Operator == Operator.Equal)
178-
{
179-
isIndexTreeAvailable = true;
180-
// find out the primary key
181-
List<AtomValue> wrappedPrimaryKey = _recordManager.SelectRecord(statement.Condition.Ands[indexSchema.SQL.AttributeName].RightOperand.ConcreteValue, indexSchema.RootPage);
182-
primaryKey = wrappedPrimaryKey?[0];
183-
break;
184-
}
185-
}
186-
}
187-
SelectResult result = new SelectResult();
188-
result.ColumnDeclarations = tableSchema.SQL.AttributeDeclarations;
189-
// index tree is not available
190-
if (!isIndexTreeAvailable)
191-
{
192-
// select records from table tree
193-
List<List<AtomValue>> rows = _recordManager.SelectRecords(statement, tableSchema.SQL.PrimaryKey, tableSchema.SQL.AttributeDeclarations, tableSchema.RootPage);
194-
result.Rows = rows;
195-
}
196-
// index tree is available
197-
else
198-
{
199-
// select one record from table tree
200-
List<List<AtomValue>> rows = new List<List<AtomValue>>();
201-
if (!object.ReferenceEquals(primaryKey, null))
202-
{
203-
List<AtomValue> recordFromTable = _recordManager.SelectRecord(primaryKey, tableSchema.RootPage);
204-
rows.Add(recordFromTable);
205-
result.Rows = rows;
206-
}
207-
else // the primary key is null.
208-
// if primaryKey is null,
209-
// it means that from the index tree it could not find the primary key.
210-
// in order words, there is not a row existing in the table tree satisfying the condition.
211-
// thus, no need to visit the table tree
212-
{
213-
// assign an empty list
214-
result.Rows = new List<List<AtomValue>>();
215-
}
216-
}
217-
return result;
53+
_pager.Close();
21854
}
21955

220-
private void HandleStatement(InsertStatement statement)
56+
public void FlushPages()
22157
{
222-
_catalogManager.CheckValidation(statement);
223-
// get table schema
224-
SchemaRecord schema = _catalogManager.GetTableSchemaRecord(statement.TableName);
225-
// adjust inlined type in insert statement
226-
if (schema.SQL.AttributeDeclarations.Count != statement.Values.Count)
227-
{
228-
throw new Exception("number of columns between \"create table\" and \"insert statement\' do not match");
229-
}
230-
int i;
231-
for (i = 0; i < statement.Values.Count; i++)
232-
{
233-
statement.Values[i].CharLimit = schema.SQL.AttributeDeclarations[i].CharLimit;
234-
}
235-
// find out primary key from insert values
236-
AtomValue primaryKey =
237-
statement.Values[schema.SQL.AttributeDeclarations.FindIndex(x =>
238-
x.AttributeName == schema.SQL.PrimaryKey)];
239-
// insert into index trees
240-
List<SchemaRecord> indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName);
241-
foreach (SchemaRecord indexSchema in indexSchemas)
242-
{
243-
// find indexed value from insert values
244-
AtomValue indexedValue =
245-
statement.Values[schema.SQL.AttributeDeclarations.FindIndex(x =>
246-
x.AttributeName == indexSchema.SQL.AttributeName)];
247-
// wrap up indexed value and primary key
248-
List<AtomValue> indexPrimaryKeyPair = new List<AtomValue>() { indexedValue, primaryKey };
249-
// insert into index trees
250-
int newIndexRoot = _recordManager.InsertRecord(indexPrimaryKeyPair, indexedValue, indexSchema.RootPage);
251-
_catalogManager.TryUpdateSchemaRecord(indexSchema.Name, newIndexRoot);
252-
}
253-
// insert into table tree
254-
int newRoot = _recordManager.InsertRecord(statement.Values, primaryKey, schema.RootPage);
255-
_catalogManager.TryUpdateSchemaRecord(statement.TableName, newRoot);
58+
_pager.CleanAllPagesFromMainMemory();
25659
}
25760

258-
private Query Parse(string sql)
61+
public List<SelectResult> Query(string input)
25962
{
260-
return _interpreter.GetQuery(sql);
63+
List<SelectResult> selectResults = _database.Query(input.ToString());
64+
return selectResults;
26165
}
26266
}
26367
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11

2-
using MiniSQL.Api.Controllers;
32
using MiniSQL.BufferManager.Controllers;
43
using MiniSQL.CatalogManager.Controllers;
54
using MiniSQL.IndexManager.Controllers;
@@ -8,11 +7,11 @@
87
using MiniSQL.Library.Interfaces;
98
using MiniSQL.RecordManager;
109

11-
namespace MiniSQL.Startup.Controllers
10+
namespace MiniSQL.Api.Controllers
1211
{
13-
public class ApiPagerBuilder
12+
public class DatabaseBuilder
1413
{
15-
public (IApi, Pager) UseDatabase(string databaseName)
14+
public (IDatabaseController, Pager) UseDatabase(string databaseName)
1615
{
1716
// init
1817
string dbPath = $"./{databaseName}.minidb";
@@ -22,9 +21,9 @@ public class ApiPagerBuilder
2221
IInterpreter interpreter = new Parsing();
2322
ICatalogManager catalogManager = new Catalog(databaseName);
2423
IRecordManager recordManager = new RecordContext(pager, bTreeController);
25-
IApi api = new ApiController(interpreter, catalogManager, recordManager);
24+
IDatabaseController database = new DatabaseController(interpreter, catalogManager, recordManager);
2625

27-
return (api, pager);
26+
return (database, pager);
2827
}
2928
}
3029
}

0 commit comments

Comments
 (0)