diff --git a/src/MiniSQL.Api/Controllers/ApiController.cs b/src/MiniSQL.Api/Controllers/ApiController.cs index 6988f02..f7af6af 100644 --- a/src/MiniSQL.Api/Controllers/ApiController.cs +++ b/src/MiniSQL.Api/Controllers/ApiController.cs @@ -1,263 +1,67 @@ + using System.Collections.Generic; -using MiniSQL.Library.Models; +using System.IO; +using MiniSQL.BufferManager.Controllers; using MiniSQL.Library.Interfaces; -using System; -using System.Linq; +using MiniSQL.Library.Models; namespace MiniSQL.Api.Controllers { public class ApiController : IApi { + private readonly DatabaseBuilder _builder; - private readonly IInterpreter _interpreter; - private readonly ICatalogManager _catalogManager; - private readonly IRecordManager _recordManager; - - public ApiController(IInterpreter interpreter, ICatalogManager catalogManager, IRecordManager recordManager) - { - _catalogManager = catalogManager; - _interpreter = interpreter; - _recordManager = recordManager; - } + private IDatabaseController _database; + private Pager _pager; - public List Query(string sql) - { - List selectResults = new List(); - Query query; - try - { - query = Parse(sql); - } - catch (Exception ex) - { - throw new StatementPreCheckException(ex.Message, ex.InnerException); - } - foreach (IStatement statement in query.StatementList) - { - SelectResult selectResult = HandleStatement(statement); - if (selectResult != null) - { - selectResults.Add(selectResult); - } - } - return selectResults; - } + public bool IsUsingDatabase { get; private set; } = false; + private string _nameOfDatabaseInUse; - private SelectResult HandleStatement(IStatement statement) + public ApiController(DatabaseBuilder builder) { - SelectResult selectResult = null; - switch (statement.Type) - { - case StatementType.CreateStatement: - HandleStatement((CreateStatement)statement); - break; - case StatementType.DropStatement: - HandleStatement((DropStatement)statement); - break; - case StatementType.DeleteStatement: - HandleStatement((DeleteStatement)statement); - break; - case StatementType.InsertStatement: - HandleStatement((InsertStatement)statement); - break; - case StatementType.SelectStatement: - selectResult = HandleSelectStatement((SelectStatement)statement); - break; - case StatementType.ShowStatement: - selectResult = HandleSelectStatement((ShowStatement)statement); - break; - case StatementType.ExecFileStatement: - throw new Exception("Impossible reach"); - } - return selectResult; - } - - // create statement - private void HandleStatement(CreateStatement statement) - { - _catalogManager.CheckValidation(statement); - switch (statement.CreateType) - { - case CreateType.Table: - int newTableRoot = _recordManager.CreateTable(); - _catalogManager.CreateStatement(statement, newTableRoot); - break; - case CreateType.Index: - SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName); - int newIndexRoot = _recordManager.CreateIndex(tableSchema.RootPage, statement.AttributeName, tableSchema.SQL.AttributeDeclarations); - _catalogManager.CreateStatement(statement, newIndexRoot); - break; - } + _builder = builder; } - // drop statement - private void HandleStatement(DropStatement statement) + // use database + public void ChangeContext(string newDatabaseName) { - _catalogManager.CheckValidation(statement); - SchemaRecord schema; - switch (statement.TargetType) + if (IsUsingDatabase) { - case DropTarget.Table: - schema = _catalogManager.GetTableSchemaRecord(statement.TableName); - List indices = _catalogManager.GetIndicesSchemaRecord(statement.TableName); - // drop table - _catalogManager.DropStatement(statement); - _recordManager.DropTable(schema.RootPage); - // drop index trees - foreach (SchemaRecord index in indices) - { - _recordManager.DropTable(index.RootPage); - } - break; - case DropTarget.Index: - schema = _catalogManager.GetIndexSchemaRecord(statement.IndexName); - _catalogManager.DropStatement(statement); - _recordManager.DropTable(schema.RootPage); - break; + _pager.Close(); } + // init + this.IsUsingDatabase = true; + this._nameOfDatabaseInUse = newDatabaseName; + (_database, _pager) = _builder.UseDatabase(newDatabaseName); } - // delete statement - // NOTICE: relative index trees will NOT change accordingly - private void HandleStatement(DeleteStatement statement) - { - // get table and indices - _catalogManager.CheckValidation(statement); - SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName); - List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName); - - // TODO - // delete index records from index trees - // __problem__: - // attribute names := (priKey, a, b, c) - // condition := b < 3 and c > 5 - // fun facts: b and c both have index trees - // issue: to delete the records satisfying the condition above - - // delete record from table tree - int newTableRootPage = _recordManager.DeleteRecords(statement.Condition, tableSchema.SQL.PrimaryKey, tableSchema.SQL.AttributeDeclarations, tableSchema.RootPage); - _catalogManager.TryUpdateSchemaRecord(statement.TableName, newTableRootPage); - } - - private SelectResult HandleSelectStatement(ShowStatement statement) + // delete database file + public void DropDatabase(string databaseName) { - List tableSchemas = _catalogManager.GetTablesSchemaRecord(); - SelectResult result = new SelectResult(); - result.ColumnDeclarations = new List() { new AttributeDeclaration() {AttributeName = "Table", Type = AttributeTypes.Char, CharLimit = 80}}; - result.Rows = new List>(); - foreach (SchemaRecord tableSchema in tableSchemas) + if (_nameOfDatabaseInUse == databaseName) { - List row = new List(); - AtomValue col = new AtomValue(); - col.Type = AttributeTypes.Char; - col.CharLimit = 80; - col.StringValue = tableSchema.Name; - row.Add(col); - result.Rows.Add(row); + _pager.Close(); + IsUsingDatabase = false; } - return result; + File.Delete($"{databaseName}.minidb"); + File.Delete($"{databaseName}.indices.dbcatalog"); + File.Delete($"{databaseName}.tables.dbcatalog"); } - private SelectResult HandleSelectStatement(SelectStatement statement) + public void ClosePager() { - bool isIndexTreeAvailable = false; - // get table and indices - _catalogManager.CheckValidation(statement); - SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.FromTable); - List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.FromTable); - - // select from index tree if possible - AtomValue primaryKey = null; - if (statement.Condition != null) - { - foreach (SchemaRecord indexSchema in indexSchemas) - { - // if there has a condition `=` on indexed column - if (statement.Condition.Ands.ContainsKey(indexSchema.SQL.AttributeName) - && statement.Condition.Ands[indexSchema.SQL.AttributeName].Operator == Operator.Equal) - { - isIndexTreeAvailable = true; - // find out the primary key - List wrappedPrimaryKey = _recordManager.SelectRecord(statement.Condition.Ands[indexSchema.SQL.AttributeName].RightOperand.ConcreteValue, indexSchema.RootPage); - primaryKey = wrappedPrimaryKey?[0]; - break; - } - } - } - SelectResult result = new SelectResult(); - result.ColumnDeclarations = tableSchema.SQL.AttributeDeclarations; - // index tree is not available - if (!isIndexTreeAvailable) - { - // select records from table tree - List> rows = _recordManager.SelectRecords(statement, tableSchema.SQL.PrimaryKey, tableSchema.SQL.AttributeDeclarations, tableSchema.RootPage); - result.Rows = rows; - } - // index tree is available - else - { - // select one record from table tree - List> rows = new List>(); - if (!object.ReferenceEquals(primaryKey, null)) - { - List recordFromTable = _recordManager.SelectRecord(primaryKey, tableSchema.RootPage); - rows.Add(recordFromTable); - result.Rows = rows; - } - else // the primary key is null. - // if primaryKey is null, - // it means that from the index tree it could not find the primary key. - // in order words, there is not a row existing in the table tree satisfying the condition. - // thus, no need to visit the table tree - { - // assign an empty list - result.Rows = new List>(); - } - } - return result; + _pager.Close(); } - private void HandleStatement(InsertStatement statement) + public void FlushPages() { - _catalogManager.CheckValidation(statement); - // get table schema - SchemaRecord schema = _catalogManager.GetTableSchemaRecord(statement.TableName); - // adjust inlined type in insert statement - if (schema.SQL.AttributeDeclarations.Count != statement.Values.Count) - { - throw new Exception("number of columns between \"create table\" and \"insert statement\' do not match"); - } - int i; - for (i = 0; i < statement.Values.Count; i++) - { - statement.Values[i].CharLimit = schema.SQL.AttributeDeclarations[i].CharLimit; - } - // find out primary key from insert values - AtomValue primaryKey = - statement.Values[schema.SQL.AttributeDeclarations.FindIndex(x => - x.AttributeName == schema.SQL.PrimaryKey)]; - // insert into index trees - List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName); - foreach (SchemaRecord indexSchema in indexSchemas) - { - // find indexed value from insert values - AtomValue indexedValue = - statement.Values[schema.SQL.AttributeDeclarations.FindIndex(x => - x.AttributeName == indexSchema.SQL.AttributeName)]; - // wrap up indexed value and primary key - List indexPrimaryKeyPair = new List() { indexedValue, primaryKey }; - // insert into index trees - int newIndexRoot = _recordManager.InsertRecord(indexPrimaryKeyPair, indexedValue, indexSchema.RootPage); - _catalogManager.TryUpdateSchemaRecord(indexSchema.Name, newIndexRoot); - } - // insert into table tree - int newRoot = _recordManager.InsertRecord(statement.Values, primaryKey, schema.RootPage); - _catalogManager.TryUpdateSchemaRecord(statement.TableName, newRoot); + _pager.CleanAllPagesFromMainMemory(); } - private Query Parse(string sql) + public List Query(string input) { - return _interpreter.GetQuery(sql); + List selectResults = _database.Query(input.ToString()); + return selectResults; } } } diff --git a/src/MiniSQL.Startup/Controllers/ApiPagerBuilder.cs b/src/MiniSQL.Api/Controllers/ApiPagerBuilder.cs similarity index 72% rename from src/MiniSQL.Startup/Controllers/ApiPagerBuilder.cs rename to src/MiniSQL.Api/Controllers/ApiPagerBuilder.cs index 9a87e45..caeb01a 100644 --- a/src/MiniSQL.Startup/Controllers/ApiPagerBuilder.cs +++ b/src/MiniSQL.Api/Controllers/ApiPagerBuilder.cs @@ -1,5 +1,4 @@ -using MiniSQL.Api.Controllers; using MiniSQL.BufferManager.Controllers; using MiniSQL.CatalogManager.Controllers; using MiniSQL.IndexManager.Controllers; @@ -8,11 +7,11 @@ using MiniSQL.Library.Interfaces; using MiniSQL.RecordManager; -namespace MiniSQL.Startup.Controllers +namespace MiniSQL.Api.Controllers { - public class ApiPagerBuilder + public class DatabaseBuilder { - public (IApi, Pager) UseDatabase(string databaseName) + public (IDatabaseController, Pager) UseDatabase(string databaseName) { // init string dbPath = $"./{databaseName}.minidb"; @@ -22,9 +21,9 @@ public class ApiPagerBuilder IInterpreter interpreter = new Parsing(); ICatalogManager catalogManager = new Catalog(databaseName); IRecordManager recordManager = new RecordContext(pager, bTreeController); - IApi api = new ApiController(interpreter, catalogManager, recordManager); + IDatabaseController database = new DatabaseController(interpreter, catalogManager, recordManager); - return (api, pager); + return (database, pager); } } } diff --git a/src/MiniSQL.Api/Controllers/DatabaseController.cs b/src/MiniSQL.Api/Controllers/DatabaseController.cs new file mode 100644 index 0000000..a0dd850 --- /dev/null +++ b/src/MiniSQL.Api/Controllers/DatabaseController.cs @@ -0,0 +1,264 @@ +using System.Collections.Generic; +using MiniSQL.Library.Models; +using MiniSQL.Library.Interfaces; +using System; +using System.Linq; +using MiniSQL.Library.Exceptions; + +namespace MiniSQL.Api.Controllers +{ + public class DatabaseController : IDatabaseController + { + + private readonly IInterpreter _interpreter; + private readonly ICatalogManager _catalogManager; + private readonly IRecordManager _recordManager; + + public DatabaseController(IInterpreter interpreter, ICatalogManager catalogManager, IRecordManager recordManager) + { + _catalogManager = catalogManager; + _interpreter = interpreter; + _recordManager = recordManager; + } + + public List Query(string sql) + { + List selectResults = new List(); + Query query; + try + { + query = Parse(sql); + } + catch (Exception ex) + { + throw new StatementPreCheckException(ex.Message, ex.InnerException); + } + foreach (IStatement statement in query.StatementList) + { + SelectResult selectResult = HandleStatement(statement); + if (selectResult != null) + { + selectResults.Add(selectResult); + } + } + return selectResults; + } + + private SelectResult HandleStatement(IStatement statement) + { + SelectResult selectResult = null; + switch (statement.Type) + { + case StatementType.CreateStatement: + HandleStatement((CreateStatement)statement); + break; + case StatementType.DropStatement: + HandleStatement((DropStatement)statement); + break; + case StatementType.DeleteStatement: + HandleStatement((DeleteStatement)statement); + break; + case StatementType.InsertStatement: + HandleStatement((InsertStatement)statement); + break; + case StatementType.SelectStatement: + selectResult = HandleSelectStatement((SelectStatement)statement); + break; + case StatementType.ShowStatement: + selectResult = HandleSelectStatement((ShowStatement)statement); + break; + case StatementType.ExecFileStatement: + throw new Exception("Impossible reach"); + } + return selectResult; + } + + // create statement + private void HandleStatement(CreateStatement statement) + { + _catalogManager.CheckValidation(statement); + switch (statement.CreateType) + { + case CreateType.Table: + int newTableRoot = _recordManager.CreateTable(); + _catalogManager.CreateStatement(statement, newTableRoot); + break; + case CreateType.Index: + SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName); + int newIndexRoot = _recordManager.CreateIndex(tableSchema.RootPage, statement.AttributeName, tableSchema.SQL.AttributeDeclarations); + _catalogManager.CreateStatement(statement, newIndexRoot); + break; + } + } + + // drop statement + private void HandleStatement(DropStatement statement) + { + _catalogManager.CheckValidation(statement); + SchemaRecord schema; + switch (statement.TargetType) + { + case DropTarget.Table: + schema = _catalogManager.GetTableSchemaRecord(statement.TableName); + List indices = _catalogManager.GetIndicesSchemaRecord(statement.TableName); + // drop table + _catalogManager.DropStatement(statement); + _recordManager.DropTable(schema.RootPage); + // drop index trees + foreach (SchemaRecord index in indices) + { + _recordManager.DropTable(index.RootPage); + } + break; + case DropTarget.Index: + schema = _catalogManager.GetIndexSchemaRecord(statement.IndexName); + _catalogManager.DropStatement(statement); + _recordManager.DropTable(schema.RootPage); + break; + } + } + + // delete statement + // NOTICE: relative index trees will NOT change accordingly + private void HandleStatement(DeleteStatement statement) + { + // get table and indices + _catalogManager.CheckValidation(statement); + SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName); + List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName); + + // TODO + // delete index records from index trees + // __problem__: + // attribute names := (priKey, a, b, c) + // condition := b < 3 and c > 5 + // fun facts: b and c both have index trees + // issue: to delete the records satisfying the condition above + + // delete record from table tree + int newTableRootPage = _recordManager.DeleteRecords(statement.Condition, tableSchema.SQL.PrimaryKey, tableSchema.SQL.AttributeDeclarations, tableSchema.RootPage); + _catalogManager.TryUpdateSchemaRecord(statement.TableName, newTableRootPage); + } + + private SelectResult HandleSelectStatement(ShowStatement statement) + { + List tableSchemas = _catalogManager.GetTablesSchemaRecord(); + SelectResult result = new SelectResult(); + result.ColumnDeclarations = new List() { new AttributeDeclaration() {AttributeName = "Table", Type = AttributeTypes.Char, CharLimit = 80}}; + result.Rows = new List>(); + foreach (SchemaRecord tableSchema in tableSchemas) + { + List row = new List(); + AtomValue col = new AtomValue(); + col.Type = AttributeTypes.Char; + col.CharLimit = 80; + col.StringValue = tableSchema.Name; + row.Add(col); + result.Rows.Add(row); + } + return result; + } + + private SelectResult HandleSelectStatement(SelectStatement statement) + { + bool isIndexTreeAvailable = false; + // get table and indices + _catalogManager.CheckValidation(statement); + SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.FromTable); + List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.FromTable); + + // select from index tree if possible + AtomValue primaryKey = null; + if (statement.Condition != null) + { + foreach (SchemaRecord indexSchema in indexSchemas) + { + // if there has a condition `=` on indexed column + if (statement.Condition.Ands.ContainsKey(indexSchema.SQL.AttributeName) + && statement.Condition.Ands[indexSchema.SQL.AttributeName].Operator == Operator.Equal) + { + isIndexTreeAvailable = true; + // find out the primary key + List wrappedPrimaryKey = _recordManager.SelectRecord(statement.Condition.Ands[indexSchema.SQL.AttributeName].RightOperand.ConcreteValue, indexSchema.RootPage); + primaryKey = wrappedPrimaryKey?[0]; + break; + } + } + } + SelectResult result = new SelectResult(); + result.ColumnDeclarations = tableSchema.SQL.AttributeDeclarations; + // index tree is not available + if (!isIndexTreeAvailable) + { + // select records from table tree + List> rows = _recordManager.SelectRecords(statement, tableSchema.SQL.PrimaryKey, tableSchema.SQL.AttributeDeclarations, tableSchema.RootPage); + result.Rows = rows; + } + // index tree is available + else + { + // select one record from table tree + List> rows = new List>(); + if (!object.ReferenceEquals(primaryKey, null)) + { + List recordFromTable = _recordManager.SelectRecord(primaryKey, tableSchema.RootPage); + rows.Add(recordFromTable); + result.Rows = rows; + } + else // the primary key is null. + // if primaryKey is null, + // it means that from the index tree it could not find the primary key. + // in order words, there is not a row existing in the table tree satisfying the condition. + // thus, no need to visit the table tree + { + // assign an empty list + result.Rows = new List>(); + } + } + return result; + } + + private void HandleStatement(InsertStatement statement) + { + _catalogManager.CheckValidation(statement); + // get table schema + SchemaRecord schema = _catalogManager.GetTableSchemaRecord(statement.TableName); + // adjust inlined type in insert statement + if (schema.SQL.AttributeDeclarations.Count != statement.Values.Count) + { + throw new Exception("number of columns between \"create table\" and \"insert statement\' do not match"); + } + int i; + for (i = 0; i < statement.Values.Count; i++) + { + statement.Values[i].CharLimit = schema.SQL.AttributeDeclarations[i].CharLimit; + } + // find out primary key from insert values + AtomValue primaryKey = + statement.Values[schema.SQL.AttributeDeclarations.FindIndex(x => + x.AttributeName == schema.SQL.PrimaryKey)]; + // insert into index trees + List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName); + foreach (SchemaRecord indexSchema in indexSchemas) + { + // find indexed value from insert values + AtomValue indexedValue = + statement.Values[schema.SQL.AttributeDeclarations.FindIndex(x => + x.AttributeName == indexSchema.SQL.AttributeName)]; + // wrap up indexed value and primary key + List indexPrimaryKeyPair = new List() { indexedValue, primaryKey }; + // insert into index trees + int newIndexRoot = _recordManager.InsertRecord(indexPrimaryKeyPair, indexedValue, indexSchema.RootPage); + _catalogManager.TryUpdateSchemaRecord(indexSchema.Name, newIndexRoot); + } + // insert into table tree + int newRoot = _recordManager.InsertRecord(statement.Values, primaryKey, schema.RootPage); + _catalogManager.TryUpdateSchemaRecord(statement.TableName, newRoot); + } + + private Query Parse(string sql) + { + return _interpreter.GetQuery(sql); + } + } +} diff --git a/src/MiniSQL.Api/Interfaces/IDatabaseController.cs b/src/MiniSQL.Api/Interfaces/IDatabaseController.cs new file mode 100644 index 0000000..9e71093 --- /dev/null +++ b/src/MiniSQL.Api/Interfaces/IDatabaseController.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using MiniSQL.Library.Models; + +namespace MiniSQL.Library.Interfaces +{ + public interface IDatabaseController + { + // return empty list (not null) if nothing to return + List Query(string sql); + } +} diff --git a/src/MiniSQL.CatalogManager/Controllers/Catalog.cs b/src/MiniSQL.CatalogManager/Controllers/Catalog.cs index 9defcf2..76ca034 100644 --- a/src/MiniSQL.CatalogManager/Controllers/Catalog.cs +++ b/src/MiniSQL.CatalogManager/Controllers/Catalog.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using MiniSQL.CatalogManager.Controllers; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; diff --git a/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs b/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs index a3025d1..bffd927 100644 --- a/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs +++ b/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs @@ -2,6 +2,7 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; using MiniSQL.CatalogManager.Models; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; diff --git a/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs b/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs index bcef0e9..9baa45f 100644 --- a/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs +++ b/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs @@ -2,6 +2,7 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; using MiniSQL.CatalogManager.Models; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.cs index 2b36b4a..6038fe1 100644 --- a/src/MiniSQL.IndexManager/Controllers/BTreeController.cs +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.cs @@ -7,6 +7,7 @@ using MiniSQL.Library.Models; using MiniSQL.IndexManager.Utilities; using MiniSQL.Library.Interfaces; +using MiniSQL.Library.Exceptions; namespace MiniSQL.IndexManager.Controllers { diff --git a/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs b/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs index a72b998..056bcc1 100644 --- a/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs +++ b/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs @@ -5,12 +5,6 @@ namespace MiniSQL.IndexManager.Interfaces { - public class RepeatedKeyException : Exception - { - public RepeatedKeyException() { } - public RepeatedKeyException(string message) : base(message) { } - } - public interface IIndexManager { // when create table diff --git a/src/MiniSQL.IndexManager/Program.cs b/src/MiniSQL.IndexManager/Program.cs index ffd9f0f..230bea0 100644 --- a/src/MiniSQL.IndexManager/Program.cs +++ b/src/MiniSQL.IndexManager/Program.cs @@ -8,6 +8,7 @@ using MiniSQL.IndexManager.Interfaces; using MiniSQL.IndexManager.Models; using MiniSQL.IndexManager.Utilities; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Models; namespace MiniSQL.IndexManager diff --git a/src/MiniSQL.Library/Exceptions/Exceptions.cs b/src/MiniSQL.Library/Exceptions/Exceptions.cs new file mode 100644 index 0000000..6540b41 --- /dev/null +++ b/src/MiniSQL.Library/Exceptions/Exceptions.cs @@ -0,0 +1,81 @@ +using System; + +namespace MiniSQL.Library.Exceptions +{ + public class StatementPreCheckException : Exception + { + public StatementPreCheckException() + { } + public StatementPreCheckException(string message) + : base(message) { } + public StatementPreCheckException(string message, Exception inner) + : base(message, inner) { } + } + + public class RepeatedKeyException : Exception + { + public RepeatedKeyException() { } + public RepeatedKeyException(string message) : base(message) { } + } + + public class TableOrIndexAlreadyExistsException : Exception + { + public TableOrIndexAlreadyExistsException() + { } + public TableOrIndexAlreadyExistsException(string message) + : base(message) { } + public TableOrIndexAlreadyExistsException(string message, Exception inner) + : base(message, inner) { } + } + + public class TableOrIndexNotExistsException : Exception + { + public TableOrIndexNotExistsException() + { } + public TableOrIndexNotExistsException(string message) + : base(message) { } + public TableOrIndexNotExistsException(string message, Exception inner) + : base(message, inner) { } + } + + public class AttributeNotExistsException : Exception + { + public AttributeNotExistsException() + { } + public AttributeNotExistsException(string message) + : base(message) { } + public AttributeNotExistsException(string message, Exception inner) + : base(message, inner) { } + } + + public class NumberOfAttributesNotMatchsException : Exception + { + public NumberOfAttributesNotMatchsException() + { } + public NumberOfAttributesNotMatchsException(string message) + : base(message) { } + public NumberOfAttributesNotMatchsException(string message, Exception inner) + : base(message, inner) { } + } + + public class TypeOfAttributeNotMatchsException : Exception + { + public TypeOfAttributeNotMatchsException() + { } + public TypeOfAttributeNotMatchsException(string message) + : base(message) { } + public TypeOfAttributeNotMatchsException(string message, Exception inner) + : base(message, inner) { } + } + + public class KeyNotExistsException : Exception + { + public KeyNotExistsException() + { } + public KeyNotExistsException(string message) + : base(message) { } + public KeyNotExistsException(string message, Exception inner) + : base(message, inner) { } + } + +} diff --git a/src/MiniSQL.Library/Interfaces/IApi.cs b/src/MiniSQL.Library/Interfaces/IApi.cs index 4de5334..33fc712 100644 --- a/src/MiniSQL.Library/Interfaces/IApi.cs +++ b/src/MiniSQL.Library/Interfaces/IApi.cs @@ -4,18 +4,13 @@ namespace MiniSQL.Library.Interfaces { - public class StatementPreCheckException : Exception - { - public StatementPreCheckException() - { } - public StatementPreCheckException(string message) - : base(message) { } - public StatementPreCheckException(string message, Exception inner) - : base(message, inner) { } - } - public interface IApi { + bool IsUsingDatabase { get; } + void ChangeContext(string newDatabaseName); + void DropDatabase(string databaseName); + void ClosePager(); + void FlushPages(); // return empty list (not null) if nothing to return List Query(string sql); } diff --git a/src/MiniSQL.Library/Interfaces/ICatalogManager.cs b/src/MiniSQL.Library/Interfaces/ICatalogManager.cs index f5de54c..b1dcecf 100644 --- a/src/MiniSQL.Library/Interfaces/ICatalogManager.cs +++ b/src/MiniSQL.Library/Interfaces/ICatalogManager.cs @@ -4,66 +4,7 @@ namespace MiniSQL.Library.Interfaces { - public class TableOrIndexAlreadyExistsException : Exception - { - public TableOrIndexAlreadyExistsException() - { } - public TableOrIndexAlreadyExistsException(string message) - : base(message) { } - public TableOrIndexAlreadyExistsException(string message, Exception inner) - : base(message, inner) { } - } - - public class TableOrIndexNotExistsException : Exception - { - public TableOrIndexNotExistsException() - { } - public TableOrIndexNotExistsException(string message) - : base(message) { } - public TableOrIndexNotExistsException(string message, Exception inner) - : base(message, inner) { } - } - - public class AttributeNotExistsException : Exception - { - public AttributeNotExistsException() - { } - public AttributeNotExistsException(string message) - : base(message) { } - public AttributeNotExistsException(string message, Exception inner) - : base(message, inner) { } - } - - public class NumberOfAttributesNotMatchsException : Exception - { - public NumberOfAttributesNotMatchsException() - { } - public NumberOfAttributesNotMatchsException(string message) - : base(message) { } - public NumberOfAttributesNotMatchsException(string message, Exception inner) - : base(message, inner) { } - } - - public class TypeOfAttributeNotMatchsException : Exception - { - public TypeOfAttributeNotMatchsException() - { } - public TypeOfAttributeNotMatchsException(string message) - : base(message) { } - public TypeOfAttributeNotMatchsException(string message, Exception inner) - : base(message, inner) { } - } - - public class KeyNotExistsException : Exception - { - public KeyNotExistsException() - { } - public KeyNotExistsException(string message) - : base(message) { } - public KeyNotExistsException(string message, Exception inner) - : base(message, inner) { } - } - + public interface ICatalogManager { // try to save the create statement into file as a few schema records diff --git a/src/MiniSQL.Startup/Controllers/DatabaseController.cs b/src/MiniSQL.Startup/Controllers/DatabaseController.cs deleted file mode 100644 index c2cd093..0000000 --- a/src/MiniSQL.Startup/Controllers/DatabaseController.cs +++ /dev/null @@ -1,67 +0,0 @@ - -using System.Collections.Generic; -using System.IO; -using MiniSQL.BufferManager.Controllers; -using MiniSQL.Library.Interfaces; -using MiniSQL.Library.Models; - -namespace MiniSQL.Startup.Controllers -{ - public class DatabaseController - { - private readonly ApiPagerBuilder _builder; - - private IApi _api; - private Pager _pager; - - public bool IsUsingDatabase { get; private set; } = false; - private string nameOfDatabaseInUse; - - public DatabaseController(ApiPagerBuilder builder) - { - _builder = builder; - } - - // use database - public void ChangeContext(string newDatabaseName) - { - if (IsUsingDatabase) - { - _pager.Close(); - } - // init - this.IsUsingDatabase = true; - this.nameOfDatabaseInUse = newDatabaseName; - (_api, _pager) = _builder.UseDatabase(newDatabaseName); - } - - // delete database file - public void DropDatabase(string databaseName) - { - if (nameOfDatabaseInUse == databaseName) - { - _pager.Close(); - IsUsingDatabase = false; - } - File.Delete($"{databaseName}.minidb"); - File.Delete($"{databaseName}.indices.dbcatalog"); - File.Delete($"{databaseName}.tables.dbcatalog"); - } - - public void ClosePager() - { - _pager.Close(); - } - - public void FlushPages() - { - _pager.CleanAllPagesFromMainMemory(); - } - - public List Query(string input) - { - List selectResults = _api.Query(input.ToString()); - return selectResults; - } - } -} diff --git a/src/MiniSQL.Startup/Controllers/View.cs b/src/MiniSQL.Startup/Controllers/View.cs index e540a8e..029f1cd 100644 --- a/src/MiniSQL.Startup/Controllers/View.cs +++ b/src/MiniSQL.Startup/Controllers/View.cs @@ -4,6 +4,7 @@ using System.Text; using System.Text.RegularExpressions; using MiniSQL.IndexManager.Interfaces; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; @@ -11,10 +12,10 @@ namespace MiniSQL.Startup.Controllers { public class View { - private readonly DatabaseController _databaseController; + private readonly IApi _databaseController; private bool isCtrlC = false; - public View(DatabaseController databaseController) + public View(IApi databaseController) { // print prologue Console.WriteLine(); diff --git a/src/MiniSQL.Startup/Program.cs b/src/MiniSQL.Startup/Program.cs index 901a55f..752901b 100644 --- a/src/MiniSQL.Startup/Program.cs +++ b/src/MiniSQL.Startup/Program.cs @@ -1,4 +1,6 @@ -using MiniSQL.Startup.Controllers; +using MiniSQL.Api.Controllers; +using MiniSQL.Library.Interfaces; +using MiniSQL.Startup.Controllers; namespace MiniSQL.Startup { @@ -6,8 +8,8 @@ class Program { static void Main(string[] args) { - ApiPagerBuilder builder = new ApiPagerBuilder(); - DatabaseController controller = new DatabaseController(builder); + DatabaseBuilder builder = new DatabaseBuilder(); + IApi controller = new ApiController(builder); View view = new View(controller); view.Interactive(); }