diff --git a/.gitignore b/.gitignore index e1eb251..01fb5bd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,6 @@ obj/ *secret* *.minidb .vs/ -index.txt -tables.txt +*.indices.dbcatalog +*.tables.dbcatalog workshop/ diff --git a/MiniSQL.sln b/MiniSQL.sln index a498c98..240ea23 100644 --- a/MiniSQL.sln +++ b/MiniSQL.sln @@ -19,6 +19,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.RecordManager", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.Library", "src\MiniSQL.Library\MiniSQL.Library.csproj", "{3EA08587-04EB-40CA-B025-5D02A9030178}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.Client", "src\MiniSQL.Client\MiniSQL.Client.csproj", "{B6695733-2C87-4D7B-B8A8-0BC444A23712}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2BFEFB2E-6CD2-47C2-A44C-4DA783C9511B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.BufferManager.Tests", "tests\MiniSQL.BufferManager.Tests\MiniSQL.BufferManager.Tests.csproj", "{F2FF97A9-B114-4C1E-9C07-34EF87044E94}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.IndexManager.Tests", "tests\MiniSQL.IndexManager.Tests\MiniSQL.IndexManager.Tests.csproj", "{0488FA91-58B7-4DB0-8C40-29296F3E07FF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.CatalogManager.Tests", "tests\MiniSQL.CatalogManager.Tests\MiniSQL.CatalogManager.Tests.csproj", "{83C24669-2F9C-4070-BE9F-465656ECD90B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.Library.Tests", "tests\MiniSQL.Library.Tests\MiniSQL.Library.Tests.csproj", "{E6F492FB-1781-4A46-9952-2091926362B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSQL.Api.Tests", "tests\MiniSQL.Api.Tests\MiniSQL.Api.Tests.csproj", "{7257DE07-C2F5-49FF-9338-677FF42C1FF7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -116,6 +130,78 @@ Global {3EA08587-04EB-40CA-B025-5D02A9030178}.Release|x64.Build.0 = Release|Any CPU {3EA08587-04EB-40CA-B025-5D02A9030178}.Release|x86.ActiveCfg = Release|Any CPU {3EA08587-04EB-40CA-B025-5D02A9030178}.Release|x86.Build.0 = Release|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Debug|x64.ActiveCfg = Debug|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Debug|x64.Build.0 = Debug|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Debug|x86.ActiveCfg = Debug|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Debug|x86.Build.0 = Debug|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Release|Any CPU.Build.0 = Release|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Release|x64.ActiveCfg = Release|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Release|x64.Build.0 = Release|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Release|x86.ActiveCfg = Release|Any CPU + {B6695733-2C87-4D7B-B8A8-0BC444A23712}.Release|x86.Build.0 = Release|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Debug|x64.ActiveCfg = Debug|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Debug|x64.Build.0 = Debug|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Debug|x86.ActiveCfg = Debug|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Debug|x86.Build.0 = Debug|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Release|Any CPU.Build.0 = Release|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Release|x64.ActiveCfg = Release|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Release|x64.Build.0 = Release|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Release|x86.ActiveCfg = Release|Any CPU + {F2FF97A9-B114-4C1E-9C07-34EF87044E94}.Release|x86.Build.0 = Release|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Debug|x64.Build.0 = Debug|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Debug|x86.Build.0 = Debug|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Release|Any CPU.Build.0 = Release|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Release|x64.ActiveCfg = Release|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Release|x64.Build.0 = Release|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Release|x86.ActiveCfg = Release|Any CPU + {0488FA91-58B7-4DB0-8C40-29296F3E07FF}.Release|x86.Build.0 = Release|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Debug|x64.ActiveCfg = Debug|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Debug|x64.Build.0 = Debug|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Debug|x86.ActiveCfg = Debug|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Debug|x86.Build.0 = Debug|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Release|Any CPU.Build.0 = Release|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Release|x64.ActiveCfg = Release|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Release|x64.Build.0 = Release|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Release|x86.ActiveCfg = Release|Any CPU + {83C24669-2F9C-4070-BE9F-465656ECD90B}.Release|x86.Build.0 = Release|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Debug|x64.ActiveCfg = Debug|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Debug|x64.Build.0 = Debug|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Debug|x86.ActiveCfg = Debug|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Debug|x86.Build.0 = Debug|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Release|Any CPU.Build.0 = Release|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Release|x64.ActiveCfg = Release|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Release|x64.Build.0 = Release|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Release|x86.ActiveCfg = Release|Any CPU + {E6F492FB-1781-4A46-9952-2091926362B2}.Release|x86.Build.0 = Release|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Debug|x64.ActiveCfg = Debug|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Debug|x64.Build.0 = Debug|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Debug|x86.ActiveCfg = Debug|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Debug|x86.Build.0 = Debug|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Release|Any CPU.Build.0 = Release|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Release|x64.ActiveCfg = Release|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Release|x64.Build.0 = Release|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Release|x86.ActiveCfg = Release|Any CPU + {7257DE07-C2F5-49FF-9338-677FF42C1FF7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {C40E4A7D-AFD1-45A0-8AA5-EE52EE583FF9} = {73A93E49-D1AE-4052-909C-AD8EED74D8D7} @@ -125,5 +211,11 @@ Global {05C292B3-4C6B-4470-9EDB-725DEF786183} = {73A93E49-D1AE-4052-909C-AD8EED74D8D7} {511A214E-372C-4D27-8EE7-50CFAD5F8505} = {73A93E49-D1AE-4052-909C-AD8EED74D8D7} {3EA08587-04EB-40CA-B025-5D02A9030178} = {73A93E49-D1AE-4052-909C-AD8EED74D8D7} + {B6695733-2C87-4D7B-B8A8-0BC444A23712} = {73A93E49-D1AE-4052-909C-AD8EED74D8D7} + {F2FF97A9-B114-4C1E-9C07-34EF87044E94} = {2BFEFB2E-6CD2-47C2-A44C-4DA783C9511B} + {0488FA91-58B7-4DB0-8C40-29296F3E07FF} = {2BFEFB2E-6CD2-47C2-A44C-4DA783C9511B} + {83C24669-2F9C-4070-BE9F-465656ECD90B} = {2BFEFB2E-6CD2-47C2-A44C-4DA783C9511B} + {E6F492FB-1781-4A46-9952-2091926362B2} = {2BFEFB2E-6CD2-47C2-A44C-4DA783C9511B} + {7257DE07-C2F5-49FF-9338-677FF42C1FF7} = {2BFEFB2E-6CD2-47C2-A44C-4DA783C9511B} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index e33513c..4e85a69 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A functioning database supporting a subset of SQL. Cross-platform. ## Run -1. Set `cwd` to `src/MiniSQL.Api/` +1. Set `pwd` to `src/MiniSQL.Client/` 1. Run command `dotnet run` 1. Type in some supported SQL 1. Type `exit` to exit @@ -18,7 +18,7 @@ A functioning database supporting a subset of SQL. Cross-platform. You will need .NET Core SDK to build and run this code. -Download link: . +Download link: . ## Supported Grammar @@ -38,27 +38,61 @@ create index stunameidx on student ( sname ); drop index stunameidx; select * from student; -select * from student where sno = ‘88888888’; -select * from student where sage> 20 and sgender = ‘F’; -select * from student where sno = ‘88888888’ or sage> 20 and sgender = ‘F’; +select * from student where sno = '88888888'; +select * from student where sage> 20 and sgender = 'F'; +select * from student where sno = '88888888' or sage> 20 and sgender = 'F'; select * from student where sage> (20 + 2) / 3; -insert into student values (‘12345678’,’wy’,22,’M’); +insert into student values ('12345678','wy',22,'M'); delete from student; -delete from student where sno = ‘88888888’; +delete from student where sno = '88888888'; -execfile "PATH_TO_SQL_FILE" ; +execfile "PATH/TO/SQL_FILE" ; -- ensure writing back all dirty pages exit + +-- write all pages back to disk +flush + +use database DATABASE_NAME +drop database DATABASE_NAME + +show tables; ``` +## Terminology + +- file := the database file +- file header := the header in the database file +- table tree := the B+ tree designed to represent a table +- index tree := the B+ tree designed to represent an index + ## Spec +### Database File Format + +The database file format mimicked that of SQLite but with some differences. + +Differences: + +- the file headers omits many fields. +- Index tree is also implemented with B+ tree, not B tree. +- Index tree utilizes `InternalTableCell` and `LeafTableCell` rather than `InternalIndexCell` and `LeafIndexCell`. In order words, index trees have the same architecture as table trees. +- Index tree could only support dropping and inserting along with the table tree but not deleting due to complicity (implemented in `DatabaseController`). +- The `key` field of the table cells is implemented with type `DBRecord`, not `int`. +- The nodes of B+ Tree each has a pointer `ParentPage` pointing to its parent. +- Leaf nodes of B+ Tree each has a pointer `RightPage` pointing to next leaf node on the right. + +Learn more from: + +- with graph - +- official - + ### 数据类型 -只要求支持三种基本数据类型:int,char(n),float,其中char(n)满足 1 <= n <= 255 。 +只要求支持三种基本数据类型:int,char(n),float。 ### 表定义 @@ -78,14 +112,17 @@ exit ## Architecture -![](img/2020-06-15-13-47-03.png) +![](img/2020-06-16-14-33-06.png) -### Interpreter +### Client + +Client 模块直接与用户交互,主要实现以下功能: -Interpreter模块直接与用户交互,主要实现以下功能: +1. 程序流程控制,即"启动并初始化 -> ‘接收命令、处理命令、显示命令结果’循环 -> 退出"流程。 + +### Interpreter -1. 程序流程控制,即"启动并初始化  ‘接收命令、处理命令、显示命令结果’循环  退出"流程。 -2. 接收并解释用户输入的命令,生成命令的内部数据结构表示,同时检查命令的语法正确性和语义正确性,对正确的命令调用API层提供的函数执行并显示执行结果,对不正确的命令显示错误信息。 +1. 接收并解释用户输入的命令,生成命令的内部数据结构表示,同时检查命令的语法正确性和语义正确性,对正确的命令调用API层提供的函数执行并显示执行结果,对不正确的命令显示错误信息。 ### API @@ -127,3 +164,18 @@ Buffer Manager负责缓冲区的管理,主要功能有: ### DB Files DB Files指构成数据库的所有数据文件,主要由记录数据文件、索引数据文件和Catalog数据文件组成。 + +## Build Project + +1. Set `pwd` to the project folder. +1. Make sure to uncomment the line in file `*.csproj`: + ```csharp + + ``` +1. Run `dotnet run` + +## TODO + +- [x] Support `create database ` +- [x] Support `drop database ` +- [ ] Show number of rows that is modified diff --git a/img/2020-06-15-13-47-03.png b/img/2020-06-15-13-47-03.png deleted file mode 100644 index 6bbe7de..0000000 Binary files a/img/2020-06-15-13-47-03.png and /dev/null differ diff --git a/img/2020-06-15-15-43-45.png b/img/2020-06-15-15-43-45.png new file mode 100644 index 0000000..f8e8b6d Binary files /dev/null and b/img/2020-06-15-15-43-45.png differ diff --git a/img/2020-06-16-14-33-06.png b/img/2020-06-16-14-33-06.png new file mode 100644 index 0000000..9116eb1 Binary files /dev/null and b/img/2020-06-16-14-33-06.png differ diff --git a/src/MiniSQL.Api/Controllers/ApiController.cs b/src/MiniSQL.Api/Controllers/ApiController.cs new file mode 100644 index 0000000..f7af6af --- /dev/null +++ b/src/MiniSQL.Api/Controllers/ApiController.cs @@ -0,0 +1,67 @@ + +using System.Collections.Generic; +using System.IO; +using MiniSQL.BufferManager.Controllers; +using MiniSQL.Library.Interfaces; +using MiniSQL.Library.Models; + +namespace MiniSQL.Api.Controllers +{ + public class ApiController : IApi + { + private readonly DatabaseBuilder _builder; + + private IDatabaseController _database; + private Pager _pager; + + public bool IsUsingDatabase { get; private set; } = false; + private string _nameOfDatabaseInUse; + + public ApiController(DatabaseBuilder builder) + { + _builder = builder; + } + + // use database + public void ChangeContext(string newDatabaseName) + { + if (IsUsingDatabase) + { + _pager.Close(); + } + // init + this.IsUsingDatabase = true; + this._nameOfDatabaseInUse = newDatabaseName; + (_database, _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 = _database.Query(input.ToString()); + return selectResults; + } + } +} diff --git a/src/MiniSQL.Api/Controllers/ApiPagerBuilder.cs b/src/MiniSQL.Api/Controllers/ApiPagerBuilder.cs new file mode 100644 index 0000000..3fd2cd0 --- /dev/null +++ b/src/MiniSQL.Api/Controllers/ApiPagerBuilder.cs @@ -0,0 +1,31 @@ + +using MiniSQL.BufferManager.Controllers; +using MiniSQL.CatalogManager.Controllers; +using MiniSQL.IndexManager.Controllers; +using MiniSQL.IndexManager.Interfaces; +using MiniSQL.Interpreter; +using MiniSQL.Interpreter.Controllers; +using MiniSQL.Library.Interfaces; +using MiniSQL.RecordManager; +using MiniSQL.RecordManager.Controllers; + +namespace MiniSQL.Api.Controllers +{ + public class DatabaseBuilder + { + public (IDatabaseController, Pager) UseDatabase(string databaseName) + { + // init + string dbPath = $"./{databaseName}.minidb"; + Pager pager = new Pager(dbPath, 1024 * 8, 400); + FreeList freeList = new FreeList(pager); + IIndexManager bTreeController = new BTreeController(pager, freeList, 40); + IInterpreter interpreter = new Parsing(); + ICatalogManager catalogManager = new Catalog(databaseName); + IRecordManager recordManager = new RecordContext(pager, bTreeController); + IDatabaseController database = new DatabaseController(interpreter, catalogManager, recordManager); + + return (database, pager); + } + } +} diff --git a/src/MiniSQL.Api/Api.cs b/src/MiniSQL.Api/Controllers/DatabaseController.cs similarity index 77% rename from src/MiniSQL.Api/Api.cs rename to src/MiniSQL.Api/Controllers/DatabaseController.cs index b2b4035..9fdcde4 100644 --- a/src/MiniSQL.Api/Api.cs +++ b/src/MiniSQL.Api/Controllers/DatabaseController.cs @@ -3,17 +3,18 @@ using MiniSQL.Library.Interfaces; using System; using System.Linq; +using MiniSQL.Library.Exceptions; -namespace MiniSQL.Api +namespace MiniSQL.Api.Controllers { - public class Api : IApi + public class DatabaseController : IDatabaseController { private readonly IInterpreter _interpreter; private readonly ICatalogManager _catalogManager; private readonly IRecordManager _recordManager; - public Api(IInterpreter interpreter, ICatalogManager catalogManager, IRecordManager recordManager) + public DatabaseController(IInterpreter interpreter, ICatalogManager catalogManager, IRecordManager recordManager) { _catalogManager = catalogManager; _interpreter = interpreter; @@ -63,6 +64,9 @@ private SelectResult HandleStatement(IStatement statement) case StatementType.SelectStatement: selectResult = HandleSelectStatement((SelectStatement)statement); break; + case StatementType.ShowStatement: + selectResult = HandleSelectStatement((ShowStatement)statement); + break; case StatementType.ExecFileStatement: throw new Exception("Impossible reach"); } @@ -72,28 +76,25 @@ private SelectResult HandleStatement(IStatement statement) // create statement private void HandleStatement(CreateStatement statement) { - if (!_catalogManager.IsValid(statement)) - throw new StatementPreCheckException("invalid create statement"); + _catalogManager.CheckValidation(statement); switch (statement.CreateType) { case CreateType.Table: int newTableRoot = _recordManager.CreateTable(); - _catalogManager.TryCreateStatement(statement, newTableRoot); + _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.TryCreateStatement(statement, newIndexRoot); + _catalogManager.CreateStatement(statement, newIndexRoot); break; } } - // TODO: review // drop statement private void HandleStatement(DropStatement statement) { - if (!_catalogManager.IsValid(statement)) - throw new StatementPreCheckException("invalid drop statement"); + _catalogManager.CheckValidation(statement); SchemaRecord schema; switch (statement.TargetType) { @@ -101,8 +102,8 @@ private void HandleStatement(DropStatement statement) schema = _catalogManager.GetTableSchemaRecord(statement.TableName); List indices = _catalogManager.GetIndicesSchemaRecord(statement.TableName); // drop table - if (_catalogManager.TryDropStatement(statement)) - _recordManager.DropTable(schema.RootPage); + _catalogManager.DropStatement(statement); + _recordManager.DropTable(schema.RootPage); // drop index trees foreach (SchemaRecord index in indices) { @@ -111,8 +112,8 @@ private void HandleStatement(DropStatement statement) break; case DropTarget.Index: schema = _catalogManager.GetIndexSchemaRecord(statement.IndexName); - if (_catalogManager.TryDropStatement(statement)) - _recordManager.DropTable(schema.RootPage); + _catalogManager.DropStatement(statement); + _recordManager.DropTable(schema.RootPage); break; } } @@ -122,21 +123,12 @@ private void HandleStatement(DropStatement statement) private void HandleStatement(DeleteStatement statement) { // get table and indices - if (!_catalogManager.IsValid(statement)) - throw new StatementPreCheckException("invalid delete statement"); + _catalogManager.CheckValidation(statement); SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.TableName); List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.TableName); - // // delete index records from index trees - // foreach (SchemaRecord indexSchema in indexSchemas) - // { - // // build condition for each index tree - // Expression condition = new Expression(); - - - // } - // TODO + // delete index records from index trees // __problem__: // attribute names := (priKey, a, b, c) // condition := b < 3 and c> 5 @@ -148,12 +140,30 @@ private void HandleStatement(DeleteStatement statement) _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 - if (!_catalogManager.IsValid(statement)) - throw new StatementPreCheckException("invalid select statement"); + _catalogManager.CheckValidation(statement); SchemaRecord tableSchema = _catalogManager.GetTableSchemaRecord(statement.FromTable); List indexSchemas = _catalogManager.GetIndicesSchemaRecord(statement.FromTable); @@ -164,15 +174,13 @@ private SelectResult HandleSelectStatement(SelectStatement statement) 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) + if (statement.Condition.SimpleMinterms.ContainsKey(indexSchema.SQL.AttributeName) + && statement.Condition.SimpleMinterms[indexSchema.SQL.AttributeName].Operator == Operator.Equal) { isIndexTreeAvailable = true; // find out the primary key - // List indexPrimaryKeyPair = _recordManager.SelectRecord(statement.Condition.Ands[indexSchema.Name].RightOperant.ConcreteValue, indexSchema.RootPage); - // primaryKey = indexPrimaryKeyPair[1]; - List wrappedPrimaryKey = _recordManager.SelectRecord(statement.Condition.Ands[indexSchema.SQL.AttributeName].RightOperant.ConcreteValue, indexSchema.RootPage); - primaryKey = wrappedPrimaryKey?[0]; + List wrappedPrimaryKey = _recordManager.SelectRecord(statement.Condition.SimpleMinterms[indexSchema.SQL.AttributeName].RightOperand.ConcreteValue, indexSchema.RootPage); + primaryKey = wrappedPrimaryKey?[1]; break; } } @@ -199,8 +207,8 @@ private SelectResult HandleSelectStatement(SelectStatement statement) } else // the primary key is null. // if primaryKey is null, - // it means from the index tree could not find the primary key. - // in order words, there is not a row with the condition existing in table tree. + // 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 @@ -212,8 +220,7 @@ private SelectResult HandleSelectStatement(SelectStatement statement) private void HandleStatement(InsertStatement statement) { - if (!_catalogManager.IsValid(statement)) - throw new StatementPreCheckException("invalid insert statement"); + _catalogManager.CheckValidation(statement); // get table schema SchemaRecord schema = _catalogManager.GetTableSchemaRecord(statement.TableName); // adjust inlined type in insert statement 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.Api/MiniSQL.Api.csproj b/src/MiniSQL.Api/MiniSQL.Api.csproj index 8ae0832..f07419a 100644 --- a/src/MiniSQL.Api/MiniSQL.Api.csproj +++ b/src/MiniSQL.Api/MiniSQL.Api.csproj @@ -9,8 +9,8 @@ - Exe - netcoreapp3.1 + + net5.0 diff --git a/src/MiniSQL.Api/Program.cs b/src/MiniSQL.Api/Program.cs index bba3e4b..982211d 100644 --- a/src/MiniSQL.Api/Program.cs +++ b/src/MiniSQL.Api/Program.cs @@ -1,45 +1,12 @@ using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using MiniSQL.Api.Controllers; -using MiniSQL.BufferManager.Controllers; -using MiniSQL.BufferManager.Models; -using MiniSQL.CatalogManager; -using MiniSQL.IndexManager.Controllers; -using MiniSQL.IndexManager.Interfaces; -using MiniSQL.Interpreter; -using MiniSQL.Library.Interfaces; -using MiniSQL.Library.Models; -using MiniSQL.RecordManager; namespace MiniSQL.Api { class Program { - // TODO: view of the whole solution static void Main(string[] args) { - // init - string dbPath = "./testdbfile.minidb"; - Pager pager = new Pager(dbPath, 1024 * 8, 400); - FreeList freeList = new FreeList(pager); - IIndexManager bTreeController = new BTreeController(pager, freeList, 40); - IInterpreter interpreter = new Parsing(); - ICatalogManager catalogManager = new Catalog(); - IRecordManager recordManager = new RecordContext(pager, bTreeController); - IApi api = new Api(interpreter, catalogManager, recordManager); - - View view = new View( - bTreeController, - interpreter, - catalogManager, - recordManager, - api, - pager - ); - view.Interactive(); + Console.WriteLine("Hello world"); } } } diff --git a/src/MiniSQL.Api/tests/table-create-drop-1.sql b/src/MiniSQL.Api/tests/table-create-drop-1.sql deleted file mode 100644 index 4180854..0000000 --- a/src/MiniSQL.Api/tests/table-create-drop-1.sql +++ /dev/null @@ -1,11 +0,0 @@ -create table person ( - pid int primary key, - name char(32), - identity int, - age int, - height float, - weight float, - address char(128) -); - -drop table person; diff --git a/src/MiniSQL.IndexManager/Controllers/FreeList.cs b/src/MiniSQL.BufferManager/Controllers/FreeList.cs similarity index 88% rename from src/MiniSQL.IndexManager/Controllers/FreeList.cs rename to src/MiniSQL.BufferManager/Controllers/FreeList.cs index bae4490..d9752f7 100644 --- a/src/MiniSQL.IndexManager/Controllers/FreeList.cs +++ b/src/MiniSQL.BufferManager/Controllers/FreeList.cs @@ -1,13 +1,9 @@ using System; -using System.Collections; -using System.Collections.Generic; -using MiniSQL.BufferManager.Controllers; using MiniSQL.BufferManager.Models; -using MiniSQL.IndexManager.Models; -namespace MiniSQL.IndexManager.Controllers +namespace MiniSQL.BufferManager.Controllers { - // a link list recording all free pages + // a linked list recording all free pages public class FreeList { private readonly Pager _pager; diff --git a/src/MiniSQL.BufferManager/Controllers/Pager.cs b/src/MiniSQL.BufferManager/Controllers/Pager.cs index ff27b66..621e85f 100644 --- a/src/MiniSQL.BufferManager/Controllers/Pager.cs +++ b/src/MiniSQL.BufferManager/Controllers/Pager.cs @@ -150,6 +150,8 @@ public void ReadPage(MemoryPage page) // remove LRU if out of limit if (this.Pages.Count>= this.InMemoryPageCountLimit) RemoveLRUPage(); + if (this.Pages.Count>= this.InMemoryPageCountLimit) + throw new Exception("Race condition!"); page.Core = new MemoryPage.MemoryPageCore(this, page.PageNumber); page.Core.data = new byte[this.PageSize]; @@ -170,7 +172,8 @@ public void WritePage(MemoryPage page) this.Stream.Seek((page.PageNumber - 1) * this.PageSize, SeekOrigin.Begin); this.Stream.Write(page.Data, 0, page.PageSize); - this.Stream.Flush(true); + // WORK AROUND: make good use of OS-level buffer XD + // this.Stream.Flush(true); page.IsDirty = false; } @@ -186,6 +189,18 @@ public void Close() } } + // write back dirty pages without closing connection to the file system + // the changes will not immediately affect the file in secondary memory (the disk) + public void CleanAllPagesFromMainMemory() + { + lock (this) + { + while (this.Pages.Count> 0) + RemovePage(this.Pages.First().Value.Item1); + this.Stream.FlushAsync(); + } + } + // mark a page as active and prevent it from being swapped out public void SetPageAsMostRecentlyUsed(int pageNumber) { diff --git a/src/MiniSQL.BufferManager/MiniSQL.BufferManager.csproj b/src/MiniSQL.BufferManager/MiniSQL.BufferManager.csproj index 248046f..14d3ff9 100644 --- a/src/MiniSQL.BufferManager/MiniSQL.BufferManager.csproj +++ b/src/MiniSQL.BufferManager/MiniSQL.BufferManager.csproj @@ -5,8 +5,8 @@ - Exe - netcoreapp3.1 + + net5.0 diff --git a/src/MiniSQL.IndexManager/Models/FreeListTruck.cs b/src/MiniSQL.BufferManager/Models/FreeListTruck.cs similarity index 75% rename from src/MiniSQL.IndexManager/Models/FreeListTruck.cs rename to src/MiniSQL.BufferManager/Models/FreeListTruck.cs index dc607b2..6f3f21c 100644 --- a/src/MiniSQL.IndexManager/Models/FreeListTruck.cs +++ b/src/MiniSQL.BufferManager/Models/FreeListTruck.cs @@ -1,8 +1,10 @@ using System; -using MiniSQL.BufferManager.Models; -namespace MiniSQL.IndexManager.Models +namespace MiniSQL.BufferManager.Models { + // To keep MemoryPage intact with new functionality, + // FreeListTruck here is to wrap up the MemoryPage. + // a minimal unit in the FreeList public class FreeListTruck { private readonly MemoryPage _page; diff --git a/src/MiniSQL.BufferManager/Program.cs b/src/MiniSQL.BufferManager/Program.cs index 106de78..25286ae 100644 --- a/src/MiniSQL.BufferManager/Program.cs +++ b/src/MiniSQL.BufferManager/Program.cs @@ -14,13 +14,61 @@ static void Main(string[] args) { Console.WriteLine("[BufferManager] Test Begin"); - // TestPager(); + TestPager(); - // TestPagerSwapping(); + TestPagerSwapping(); + + TestFreeList(); Console.WriteLine("[BufferManager] Test End"); } + static void TestFreeList() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 100); + + List pageList = new List(); + pageList.Add(pager.GetNewPage()); // page #2 + pageList.Add(pager.GetNewPage()); // page #3 + pageList.Add(pager.GetNewPage()); // page #4 + pageList.Add(pager.GetNewPage()); // page #5 + + FreeList freeList = new FreeList(pager); + + // test initialization + MemoryPage newPage = null; + newPage = freeList.AllocatePage(); // freeList is now empty + Debug.Assert(newPage == null); + + // recycle pages + // MemoryPage tempPage = pager.ReadPage(3); + freeList.RecyclePage(pageList[2]); // freeList->4 + freeList.RecyclePage(pageList[1]); // freeList->3->4 + freeList.RecyclePage(pageList[3]); // freeList->5->3->4 + + // fetch page from free list + newPage = freeList.AllocatePage(); // freeList->3->4 + Debug.Assert(newPage.PageNumber == 5); + newPage = freeList.AllocatePage(); // freeList->4 + Debug.Assert(newPage.PageNumber == 3); + + // recycle a page + freeList.RecyclePage(pageList[3]); // freeList->5->4 + + // fetch remaining pages + newPage = freeList.AllocatePage(); // freeList->4 + Debug.Assert(newPage.PageNumber == 5); + newPage = freeList.AllocatePage(); // freeList->null + Debug.Assert(newPage.PageNumber == 4); + newPage = freeList.AllocatePage(); // freeList->null + Debug.Assert(newPage == null); + + pager.Close(); + } + private static Expression GetAndsExpression() { // __tree structure__ @@ -53,13 +101,13 @@ private static Expression GetAndsExpression() // <= Expression node4 = new Expression(); node4.Operator = Operator.LessThanOrEqualTo; - node4.LeftOperant = node8; - node4.RightOperant = node9; + node4.LeftOperand = node8; + node4.RightOperand = node9; // <= Expression node5 = new Expression(); node5.Operator = Operator.LessThanOrEqualTo; - node5.LeftOperant = node10; - node5.RightOperant = node11; + node5.LeftOperand = node10; + node5.RightOperand = node11; // 6.6 Expression node6 = new Expression(); node6.Operator = Operator.AtomConcreteValue; @@ -73,18 +121,18 @@ private static Expression GetAndsExpression() // and Expression node2 = new Expression(); node2.Operator = Operator.And; - node2.LeftOperant = node4; - node2.RightOperant = node5; + node2.LeftOperand = node4; + node2.RightOperand = node5; //> Expression node3 = new Expression(); node3.Operator = Operator.MoreThan; - node3.LeftOperant = node6; - node3.RightOperant = node7; + node3.LeftOperand = node6; + node3.RightOperand = node7; // and Expression node1 = new Expression(); node1.Operator = Operator.And; - node1.LeftOperant = node2; - node1.RightOperant = node3; + node1.LeftOperand = node2; + node1.RightOperand = node3; return node1; } diff --git a/src/MiniSQL.CatalogManager/CatalogManager.cs b/src/MiniSQL.CatalogManager/CatalogManager.cs deleted file mode 100644 index 619f2f9..0000000 --- a/src/MiniSQL.CatalogManager/CatalogManager.cs +++ /dev/null @@ -1,713 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using MiniSQL.Library.Interfaces; -using MiniSQL.Library.Models; - -namespace MiniSQL.CatalogManager -{ - //define all the functions - public class Catalog : ICatalogManager - { - // try to save the create statement into file as a few schema records - // if succeeded, return true. Vice versa - public bool TryCreateStatement(CreateStatement createStatement, int rootPage) - { - //create table - if (createStatement.CreateType == CreateType.Table) - { - Catalog_table a = new Catalog_table();//load the tables - return a.TryCreateStatementForTable(createStatement, rootPage); - } - //create index - else - { - Catalog_index b = new Catalog_index();//load the index - return b.TryCreateStatementForIndex(createStatement, rootPage); - } - } - // try to remove some schema records from file - // if succeeded, return true. Vice versa - public bool TryDropStatement(DropStatement dropStatement) - { - if (dropStatement.TargetType == DropTarget.Table) - { - Catalog_table a = new Catalog_table();//load the table - return a.TryDropStatementForTable(dropStatement); - } - else - { - Catalog_index b = new Catalog_index();//load the index - return b.TryDropStatementForIndex(dropStatement); - } - } - - // update the root page of a table or an index - // if succeeded, return true. Vice versa - public bool TryUpdateSchemaRecord(string name, int rootPage) - { - //load both table and index - Catalog_table a = new Catalog_table(); - Catalog_index b = new Catalog_index(); - - //if it's the name of a table - if (a.If_in(name)) - { - return a.Update(name, rootPage); - } - - //if it's the name of an index - else if (b.If_in(name)) - { - return b.Update(name, rootPage); - } - - //if it's neither index nor table - else - { - return false; - } - - } - // according to the table name required, return corresponding schema record - public SchemaRecord GetTableSchemaRecord(string tableName) - { - Catalog_table a = new Catalog_table(); - return a.GetTableSchemaRecord(tableName); - } - // according to the table name required, return the all index schema records that is associated to the table - public List GetIndicesSchemaRecord(string tableName) - { - Catalog_index b = new Catalog_index(); - return b.GetIndicesSchemaRecord(tableName); - } - // according to the index name required, return corresponding schema record - public SchemaRecord GetIndexSchemaRecord(string indexName) - { - Catalog_index b = new Catalog_index(); - return b.GetIndexSchemaRecord(indexName); - } - - // check validation of the statement - public bool IsValid(IStatement statement) - { - //check validation of createStatement - if (statement.Type == StatementType.CreateStatement) - { - CreateStatement x = (CreateStatement)statement; - //to create a table - if (x.CreateType == CreateType.Table) - { - //to check whether the table has been created before - Catalog_table a = new Catalog_table(); - return !a.If_in(x.TableName); - } - //to create an index - else - { - Catalog_table a = new Catalog_table(); - Catalog_index b = new Catalog_index(); - //to check whether the table exists - bool condition1 = a.If_in(x.TableName); - //to check whether the index has been created before - bool condition2 = !b.If_in(x.IndexName); - //to check whether the attribute is in the attribute list of the table - bool condition3 = a.return_table(x.TableName).Has_attribute(x.AttributeName); - //return true if the statement meets all the conditions.Vice Versa - return condition1 && condition2 && condition3; - } - } - //check validation of a drop statement - else if (statement.Type == StatementType.DropStatement) - { - DropStatement x = (DropStatement)statement; - Catalog_table a = new Catalog_table(); - Catalog_index b = new Catalog_index(); - //to drop a table,we need to check whether the table exists - if (x.TargetType == DropTarget.Table) - { - return a.If_in(x.TableName); - } - //to drop a index,we need to check whether the index exists - else - { - if (x.TableName != "") - return b.If_in(x.IndexName) && b.Of_table(x.IndexName) == x.TableName; - else - return b.If_in(x.IndexName); - } - } - - //check validation of a select statement - else if (statement.Type == StatementType.SelectStatement) - { - SelectStatement x = (SelectStatement)statement; - //check whether the table is in the tables catalog - Catalog_table a = new Catalog_table(); - if (!a.If_in(x.FromTable)) - { - return false; - } - if (x.Condition == null) - { - return true; - } - else if (x.Condition.AttributeName == "") - { - - if (x.Condition.Ands.Count == 0) - { - //if the ands is empty and attribute name is emply, the statement means select * from a table - return true; - } - else - { - //for each attribute in the epression list(named 'ands') - //check whether the attribute is in the attribute list of this table - foreach (KeyValuePair expression_piece in x.Condition.Ands) - { - if (!a.return_table(x.FromTable).Has_attribute(expression_piece.Key)) - { - return false; - } - } - } - - } - else - { - //check whether the only attribute is one of the table's attributes - if (!a.return_table(x.FromTable).Has_attribute(x.Condition.AttributeName)) - { - return false; - } - - } - - - return true; - } - //check validation of a delete statement - else if (statement.Type == StatementType.DeleteStatement) - { - - DeleteStatement x = (DeleteStatement)statement; - //check whether the table is in the tables catalog - Catalog_table a = new Catalog_table(); - if (!a.If_in(x.TableName)) - { - return false; - } - if (x.Condition == null) - { - return true; - } - else if (x.Condition.AttributeName == "") - { - - if (x.Condition.Ands.Count == 0) - { - //if the ands is empty and attribute name is emply, the statement means select * from a table - return true; - } - else - { - //for each attribute in the epression list(named 'ands') - //check whether the attribute is in the attribute list of this table - foreach (KeyValuePair expression_piece in x.Condition.Ands) - { - if (!a.return_table(x.TableName).Has_attribute(expression_piece.Key)) - { - return false; - } - } - } - - } - else - { - //check whether the only attribute is one of the table's attributes - if (!a.return_table(x.TableName).Has_attribute(x.Condition.AttributeName)) - { - return false; - } - - } - - - return true; - } - //check validation of an insert statement - else if (statement.Type == StatementType.InsertStatement) - { - InsertStatement x = (InsertStatement)statement; - - //check whether the table is in the table list - Catalog_table a = new Catalog_table(); - if (!a.If_in(x.TableName)) - { - return false; - } - //check if the number of the attributes perfectly match the number of the values - if (x.Values.Count != a.return_table(x.TableName).attribute_list.Count) - { - return false; - } - //check whether the type of the inserted data well suits the data definition of each attribute - for (int i = 0; i < x.Values.Count; i++) - { - if (a.return_table(x.TableName).attribute_list[i].type != x.Values[i].Type) - { - return false; - } - } - //if all data type suit, return true - return true; - - } - //check validation of a quit statement - else if (statement.Type == StatementType.QuitStatement) - { - return true; - } - - //check validation of an exec file statement - else - { - return true; - } - } - } - - [Serializable] - class Attribute - { - public string attribute_name; - public AttributeTypes type;//three kinds of type: float int char(with limit) - public bool is_unique; - public int length;//the length of string - public Attribute(string attribute_name, AttributeTypes type, bool is_unique, int length) - { - this.attribute_name = attribute_name; - this.type = type; - this.is_unique = is_unique; - this.length = length; - } - } - - [Serializable] - class Table - { - public string table_name; - public List attribute_list; - public string primary_key; - public int root_page; - public Table(CreateStatement createStatement, int root_page) - { - this.table_name = createStatement.TableName; - this.primary_key = createStatement.PrimaryKey; - this.root_page = root_page; - List temp = new List(); - //to initialize every attribute of this table - for (int i = 0; i < createStatement.AttributeDeclarations.Count; i++) - { - string AttributeName = createStatement.AttributeDeclarations[i].AttributeName; - bool IsUnique = createStatement.AttributeDeclarations[i].IsUnique; - int Length = createStatement.AttributeDeclarations[i].CharLimit; - AttributeTypes Type = createStatement.AttributeDeclarations[i].Type; - Attribute a = new Attribute(AttributeName, Type, IsUnique, Length); - temp.Add(a); - } - //assign the attribute list to the table - this.attribute_list = temp; - } - //check whether the table has such an attribute - public bool Has_attribute(string attribute_name) - { - bool flag = false; - for (int i = 0; i < attribute_list.Count; i++) - { - if (attribute_list[i].attribute_name == attribute_name) - { - flag = true; - } - } - return flag; - } - - } - - [Serializable] - class Index - { - public string table_name { get; set; } - public string attribute_name; - public string index_name; - public bool is_uniqve; - public int root_page; - public Index(CreateStatement createStatement, int root_page) - { - this.table_name = createStatement.TableName; - this.attribute_name = createStatement.AttributeName; - this.index_name = createStatement.IndexName; - this.is_uniqve = createStatement.IsUnique; - this.root_page = root_page; - - } - } - //save all the tables in the table catalog - class Catalog_table - { - public List tables; - - //return the table name 'tableName' - //warning:need to check whether the tableName is in the table catalog first - public Table return_table(string tableName) - { - for (int i = 0; i < tables.Count; i++) - { - if (tables[i].table_name == tableName) - { - return tables[i]; - } - } - //useless but for syntax correctness - return tables[tables.Count - 1]; - } - - //return the schema record of the table named table name - public SchemaRecord GetTableSchemaRecord(string tableName) - { - SchemaRecord s = new SchemaRecord(); - s.Type = SchemaTypes.Table; - s.Name = tableName; - //since this is the table and there is no table that is associated to it - s.AssociatedTable = " "; - - //get the target table first, then get the schema record from the table - Table target_table = return_table(tableName); - s.RootPage = target_table.root_page; - s.SQL = new CreateStatement(); - s.SQL.CreateType = CreateType.Table; - s.SQL.TableName = tableName; - - //there is no index information for a table - s.SQL.IndexName = " "; - s.SQL.AttributeName = " "; - - //get every attribute declaration from the target table - - List temp = new List(); - - for (int i = 0; i < target_table.attribute_list.Count; i++) - { - AttributeDeclaration attribute = new AttributeDeclaration(); - attribute.Type = target_table.attribute_list[i].type; - attribute.CharLimit = target_table.attribute_list[i].length; - attribute.IsUnique = target_table.attribute_list[i].is_unique; - attribute.AttributeName = target_table.attribute_list[i].attribute_name; - temp.Add(attribute); - } - s.SQL.AttributeDeclarations = temp; - - s.SQL.PrimaryKey = target_table.primary_key; - //Console.WriteLine("hhhh"); - return s; - } - - - - //to check if there is such a table named 'name' - //if in,then return true. Vice versa - public bool If_in(string name) - { - for (int i = 0; i < tables.Count; i++) - { - if (tables[i].table_name == name) - { - return true; - } - } - return false; - } - - //update the rootPage of the table named 'name' - //return false if not find - public bool Update(string name, int rootPage) - { - bool has_find = false; - for (int i = 0; i < tables.Count; i++) - { - if (tables[i].table_name == name) - { - tables[i].root_page = rootPage; - has_find = true; - break; - } - } - Save_table(tables); - return has_find; - } - - - //try to create one table and save the result into the file - //if succeed, return true - //if the table is already created, return false - public bool TryCreateStatementForTable(CreateStatement createStatement, int rootPage) - { - if (this.If_in(createStatement.TableName)) - { - return false; - } - Table a = new Table(createStatement, rootPage); - tables.Add(a); - Save_table(this.tables); - return true; - } - - - //try to drop one table and save the result into the file - //if succeed, return true - //if can't find table, return false - public bool TryDropStatementForTable(DropStatement dropStatement) - { - bool if_find = false; - if (this.If_in(dropStatement.TableName)) - for (int i = 0; i < this.tables.Count;) - { - if (this.tables[i].table_name == dropStatement.TableName) - { - tables.RemoveAt(i); - Save_table(tables); - if_find = true; - } - else - i++; - } - //delete all the indices that are related to the deleted table - Catalog_index b = new Catalog_index(); - return if_find && b.DeleteIndicesOfTable(dropStatement.TableName); - - - } - - //load the table from file and store the data into tables - public void Load_table() - { - if (System.IO.File.Exists("tables.txt")) - { - using (FileStream fs = new FileStream("tables.txt", FileMode.Open)) - { - BinaryFormatter bf = new BinaryFormatter(); - this.tables = bf.Deserialize(fs) as List
; - fs.Close(); - } - } - else - { - this.tables = new List
(); - } - return; - } - - //save data of tables into the file - public void Save_table(List
tables) - { - using (FileStream fs = new FileStream("tables.txt", FileMode.Create)) - { - BinaryFormatter bf = new BinaryFormatter(); - bf.Serialize(fs, tables); - fs.Close(); - } - } - - //load the tables from the txt file - public Catalog_table() - { - Load_table(); - } - } - - - class Catalog_index - { - //store all the indices - List index; - - //return the shcema record of the index named 'index_name' - //used after checking 'If_in',to make sure that the index does exist - public SchemaRecord GetIndexSchemaRecord(string index_name) - { - SchemaRecord record = new SchemaRecord(); - for (int i = 0; i < index.Count; i++) - { - if (index[i].index_name == index_name) - { - record.AssociatedTable = index[i].table_name; - record.Name = index_name; - record.RootPage = index[i].root_page; - record.Type = SchemaTypes.Index; - CreateStatement temp = new CreateStatement(); - temp.CreateType = CreateType.Index; - temp.TableName = index[i].table_name; - temp.IsUnique = index[i].is_uniqve; - temp.IndexName = index[i].index_name; - temp.AttributeName = index[i].attribute_name; - record.SQL = temp; - } - } - return record; - } - - //Only used when try to drop a table - //Delete all the indices that related to the table named tableName from the index list - public bool DeleteIndicesOfTable(string tableName) - { - for (int i = 0; i < index.Count;) - { - if (index[i].table_name == tableName) - { - index.RemoveAt(i); - - - } - else - i++; - } - Save_index(index); - return true; - } - - //return all the indices of the table named 'tableName' - public List GetIndicesSchemaRecord(string tableName) - { - List list = new List(); - for (int i = 0; i < index.Count; i++) - { - if (index[i].table_name == tableName) - { - SchemaRecord target_index = GetIndexSchemaRecord(index[i].index_name); - list.Add(target_index); - } - } - return list; - } - - - - - - //to check if there is such a index named 'name' - //if in,then return true. Vice versa - public bool If_in(string name) - { - for (int i = 0; i < index.Count; i++) - { - if (index[i].index_name == name) - { - return true; - } - } - return false; - } - - - - //update the rootPage of the index named 'name' - public bool Update(string name, int rootPage) - { - bool has_find = false; - for (int i = 0; i < index.Count; i++) - { - if (index[i].index_name == name) - { - index[i].root_page = rootPage; - has_find = true; - break; - } - } - Save_index(index); - return has_find; - } - - - public bool TryCreateStatementForIndex(CreateStatement createStatement, int rootPage) - { - //if the index already exists,then return false - if (this.If_in(createStatement.IndexName)) - { - return false; - } - Index b = new Index(createStatement, rootPage); - index.Add(b); - Save_index(this.index); - return true; - } - - - - public bool TryDropStatementForIndex(DropStatement dropStatement) - { - //if the index hasn't been created before, return false - if (!this.If_in(dropStatement.IndexName)) - { - return false; - } - for (int i = 0; i < index.Count;) - { - if (index[i].index_name == dropStatement.IndexName) - { - index.RemoveAt(i); - break; - } - else - i++; - } - Save_index(this.index); - return true; - } - - public string Of_table(string Indexname) - { - for (int i = 0; i < index.Count; i++) - if (index[i].index_name == Indexname) - return index[i].table_name; - return ""; - } - public void Load_index() - { - if (System.IO.File.Exists("index.txt")) - { - using (FileStream fs = new FileStream("index.txt", FileMode.Open)) - { - BinaryFormatter bf = new BinaryFormatter(); - this.index = bf.Deserialize(fs) as List; - fs.Close(); - } - } - else - { - this.index = new List(); - } - return; - - } - - public void Save_index(List index) - { - using (FileStream fs = new FileStream("index.txt", FileMode.Create)) - { - BinaryFormatter bf = new BinaryFormatter(); - bf.Serialize(fs, index); - fs.Close(); - } - } - public Catalog_index() - { - Load_index();//get table list from the file - } - - - } -} \ No newline at end of file diff --git a/src/MiniSQL.CatalogManager/Controllers/Catalog.cs b/src/MiniSQL.CatalogManager/Controllers/Catalog.cs new file mode 100644 index 0000000..9a19f6f --- /dev/null +++ b/src/MiniSQL.CatalogManager/Controllers/Catalog.cs @@ -0,0 +1,332 @@ +using System; +using System.Collections.Generic; +using MiniSQL.CatalogManager.Controllers; +using MiniSQL.Library.Exceptions; +using MiniSQL.Library.Interfaces; +using MiniSQL.Library.Models; + +namespace MiniSQL.CatalogManager.Controllers +{ + //define all the functions + public class Catalog : ICatalogManager + { + private readonly string _databaseName; + + public Catalog(string databaseName) + { + _databaseName = databaseName; + } + + // try to save the create statement into file as a few schema records + // if succeeded, return true. Vice versa + public bool TryCreateStatement(CreateStatement createStatement, int rootPage) + { + try + { + CreateStatement(createStatement, rootPage); + return true; + } + catch (Exception) + { + return false; + } + } + public void CreateStatement(CreateStatement createStatement, int rootPage) + { + //create table + if (createStatement.CreateType == CreateType.Table) + { + Catalog_table a = new Catalog_table(_databaseName);//load the tables + a.CreateStatementForTable(createStatement, rootPage); + } + //create index + else + { + Catalog_index b = new Catalog_index(_databaseName);//load the index + b.CreateStatementForIndex(createStatement, rootPage); + } + } + // try to remove some schema records from file + // if succeeded, return true. Vice versa + public bool TryDropStatement(DropStatement dropStatement) + { + try + { + DropStatement(dropStatement); + return true; + } + catch (Exception) + { + return false; + } + } + public void DropStatement(DropStatement dropStatement) + { + if (dropStatement.TargetType == DropTarget.Table) + { + Catalog_table a = new Catalog_table(_databaseName);//load the table + a.DropStatementForTable(dropStatement); + } + else + { + Catalog_index b = new Catalog_index(_databaseName);//load the index + b.DropStatementForIndex(dropStatement); + } + } + + // update the root page of a table or an index + // if succeeded, return true. Vice versa + public bool TryUpdateSchemaRecord(string name, int rootPage) + { + //load both table and index + Catalog_table a = new Catalog_table(_databaseName); + Catalog_index b = new Catalog_index(_databaseName); + + //if it's the name of a table + if (a.If_in(name)) + { + return a.Update(name, rootPage); + } + + //if it's the name of an index + else if (b.If_in(name)) + { + return b.Update(name, rootPage); + } + + //if it's neither index nor table + else + { + return false; + } + + } + // according to the table name required, return corresponding schema record + public SchemaRecord GetTableSchemaRecord(string tableName) + { + Catalog_table a = new Catalog_table(_databaseName); + return a.GetTableSchemaRecord(tableName); + } + // according to the table name required, return the all index schema records that is associated to the table + public List GetIndicesSchemaRecord(string tableName) + { + Catalog_index b = new Catalog_index(_databaseName); + return b.GetIndicesSchemaRecord(tableName); + } + // according to the index name required, return corresponding schema record + public SchemaRecord GetIndexSchemaRecord(string indexName) + { + Catalog_index b = new Catalog_index(_databaseName); + return b.GetIndexSchemaRecord(indexName); + } + + // check validation of the statement + public bool IsValid(IStatement statement) + { + try + { + CheckValidation(statement); + return true; + } + catch (Exception) + { + return false; + } + } + // check validation of the statement + public void CheckValidation(IStatement statement) + { + //check validation of createStatement + if (statement.Type == StatementType.CreateStatement) + { + CreateStatement x = (CreateStatement)statement; + //to create a table + if (x.CreateType == CreateType.Table) + { + // primary key not exists + if (x.PrimaryKey == null || x.PrimaryKey == "") + throw new KeyNotExistsException($"Table \"{x.TableName}\" does not have a primary key"); + //to check whether the table has been created before + Catalog_table a = new Catalog_table(_databaseName); + a.AssertNotExist(x.TableName); + } + //to create an index + else + { + // index key not exists + if (x.AttributeName == null || x.AttributeName == "") + throw new KeyNotExistsException($"Index \"{x.IndexName}\" does not have a index key"); + Catalog_table a = new Catalog_table(_databaseName); + Catalog_index b = new Catalog_index(_databaseName); + //to check whether the table exists + bool condition1 = a.If_in(x.TableName); + //to check whether the index has been created before + bool condition2 = !b.If_in(x.IndexName); + //to check whether the attribute is in the attribute list of the table + bool condition3 = a.return_table(x.TableName).Has_attribute(x.AttributeName); + if (!condition1) + throw new TableOrIndexNotExistsException($"Table \"\"{x.TableName}\"\" not exists"); + if (!condition2) + throw new TableOrIndexAlreadyExistsException($"Index \"\"{x.IndexName}\"\" not exists"); + if (!condition3) + throw new AttributeNotExistsException($"Attribute \"\"{x.AttributeName}\"\" not exists in table \"\"{x.TableName}\"\""); + } + } + //check validation of a drop statement + else if (statement.Type == StatementType.DropStatement) + { + DropStatement x = (DropStatement)statement; + Catalog_table a = new Catalog_table(_databaseName); + Catalog_index b = new Catalog_index(_databaseName); + //to drop a table,we need to check whether the table exists + if (x.TargetType == DropTarget.Table) + { + a.AssertExist(x.TableName); + } + //to drop a index,we need to check whether the index exists + else + { + if (x.TableName != "") + { + b.AssertExist(x.IndexName); + + if (b.Of_table(x.IndexName) != x.TableName) + throw new AttributeNotExistsException($"Index \"{x.IndexName}\" is not associated with table \"{x.TableName}\""); + } + else + b.AssertExist(x.IndexName); + } + } + + //check validation of a select statement + else if (statement.Type == StatementType.SelectStatement) + { + SelectStatement x = (SelectStatement)statement; + //check whether the table is in the tables catalog + Catalog_table a = new Catalog_table(_databaseName); + a.AssertExist(x.FromTable); + if (x.Condition == null) + { + return; + } + else if (x.Condition.AttributeName == "") + { + + if (x.Condition.SimpleMinterms.Count == 0) + { + //if the ands is empty and attribute name is emply, the statement means select * from a table + return; + } + else + { + //for each attribute in the egression list(named 'ands') + //check whether the attribute is in the attribute list of this table + foreach (KeyValuePair expression_piece in x.Condition.SimpleMinterms) + { + if (!a.return_table(x.FromTable).Has_attribute(expression_piece.Key)) + { + throw new AttributeNotExistsException($"Attribute \"{expression_piece.Key}\" not exists in table \"{x.FromTable}\""); + } + } + } + + } + else + { + //check whether the only attribute is one of the table's attributes + if (!a.return_table(x.FromTable).Has_attribute(x.Condition.AttributeName)) + { + throw new AttributeNotExistsException($"Attribute \"{x.Condition.AttributeName}\" not exists in table \"{x.FromTable}\""); + } + + } + return; + } + //check validation of a delete statement + else if (statement.Type == StatementType.DeleteStatement) + { + + DeleteStatement x = (DeleteStatement)statement; + //check whether the table is in the tables catalog + Catalog_table a = new Catalog_table(_databaseName); + a.AssertExist(x.TableName); + if (x.Condition == null) + { + return; + } + else if (x.Condition.AttributeName == "") + { + + if (x.Condition.SimpleMinterms.Count == 0) + { + //if the ands is empty and attribute name is emply, the statement means select * from a table + return; + } + else + { + //for each attribute in the epression list(named 'ands') + //check whether the attribute is in the attribute list of this table + foreach (KeyValuePair expression_piece in x.Condition.SimpleMinterms) + { + if (!a.return_table(x.TableName).Has_attribute(expression_piece.Key)) + { + throw new AttributeNotExistsException($"Attribute \"{expression_piece.Key}\" not exists in table \"{x.TableName}\""); + } + } + } + + } + else + { + //check whether the only attribute is one of the table's attributes + if (!a.return_table(x.TableName).Has_attribute(x.Condition.AttributeName)) + { + throw new AttributeNotExistsException($"Attribute \"{x.Condition.AttributeName}\" not exists in table \"{x.TableName}\""); + } + + } + return; + } + //check validation of an insert statement + else if (statement.Type == StatementType.InsertStatement) + { + InsertStatement x = (InsertStatement)statement; + + //check whether the table is in the table list + Catalog_table a = new Catalog_table(_databaseName); + a.AssertExist(x.TableName); + //check if the number of the attributes perfectly match the number of the values + if (x.Values.Count != a.return_table(x.TableName).attribute_list.Count) + { + throw new NumberOfAttributesNotMatchsException($"Number of attributes not matchs. Expected: \"{a.return_table(x.TableName).attribute_list.Count}\"; actual: \"{x.Values.Count}\""); + } + //check whether the type of the inserted data well suits the data definition of each attribute + for (int i = 0; i < x.Values.Count; i++) + { + if (a.return_table(x.TableName).attribute_list[i].type != x.Values[i].Type) + { + throw new TypeOfAttributeNotMatchsException($"Type for attribute \"{a.return_table(x.TableName).attribute_list[i].attribute_name}\" not matches. Expected: \"{a.return_table(x.TableName).attribute_list[i].type}\"; actual: \"{x.Values[i].Type}\""); + } + } + //if all data type suit, return true + return; + } + //check validation of a quit statement + else if (statement.Type == StatementType.QuitStatement) + { + return; + } + //check validation of an exec file statement + else + { + return; + } + } + + public List GetTablesSchemaRecord() + { + Catalog_table a = new Catalog_table(_databaseName); + return a.GetTablesSchemaRecord(); + } + } +} diff --git a/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs b/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs new file mode 100644 index 0000000..bffd927 --- /dev/null +++ b/src/MiniSQL.CatalogManager/Controllers/Catalog_index.cs @@ -0,0 +1,225 @@ +using System.Collections.Generic; +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; + +namespace MiniSQL.CatalogManager.Controllers +{ + + class Catalog_index + { + private readonly string _databaseName; + //store all the indices + List index; + + //return the shcema record of the index named 'index_name' + //used after checking 'If_in',to make sure that the index does exist + public SchemaRecord GetIndexSchemaRecord(string index_name) + { + SchemaRecord record = new SchemaRecord(); + for (int i = 0; i < index.Count; i++) + { + if (index[i].index_name == index_name) + { + record.AssociatedTable = index[i].table_name; + record.Name = index_name; + record.RootPage = index[i].root_page; + record.Type = SchemaTypes.Index; + CreateStatement temp = new CreateStatement(); + temp.CreateType = CreateType.Index; + temp.TableName = index[i].table_name; + temp.IsUnique = index[i].is_uniqve; + temp.IndexName = index[i].index_name; + temp.AttributeName = index[i].attribute_name; + record.SQL = temp; + } + } + return record; + } + + //Only used when try to drop a table + //Delete all the indices that related to the table named tableName from the index list + public bool DeleteIndicesOfTable(string tableName) + { + for (int i = 0; i < index.Count;) + { + if (index[i].table_name == tableName) + { + index.RemoveAt(i); + + + } + else + i++; + } + Save_index(index); + return true; + } + + //return all the indices of the table named 'tableName' + public List GetIndicesSchemaRecord(string tableName) + { + List list = new List(); + for (int i = 0; i < index.Count; i++) + { + if (index[i].table_name == tableName) + { + SchemaRecord target_index = GetIndexSchemaRecord(index[i].index_name); + list.Add(target_index); + } + } + return list; + } + + //to check if there is such a index named 'name' + //if in,then return true. Vice versa + public bool If_in(string name) + { + for (int i = 0; i < index.Count; i++) + { + if (index[i].index_name == name) + { + return true; + } + } + return false; + } + + public void AssertExist(string name) + { + if (!If_in(name)) + throw new TableOrIndexNotExistsException($"Index \"{name}\" not exists"); + } + + public void AssertNotExist(string name) + { + if (If_in(name)) + throw new TableOrIndexAlreadyExistsException($"Index \"{name}\" already exists"); + } + + //update the rootPage of the index named 'name' + public bool Update(string name, int rootPage) + { + bool has_find = false; + for (int i = 0; i < index.Count; i++) + { + if (index[i].index_name == name) + { + index[i].root_page = rootPage; + has_find = true; + break; + } + } + Save_index(index); + return has_find; + } + + public bool TryCreateStatementForIndex(CreateStatement createStatement, int rootPage) + { + //if the index already exists,then return false + if (this.If_in(createStatement.IndexName)) + { + return false; + } + Models.Index b = new Models.Index(createStatement, rootPage); + index.Add(b); + Save_index(this.index); + return true; + } + public void CreateStatementForIndex(CreateStatement createStatement, int rootPage) + { + //if the index already exists,then return false + if (this.If_in(createStatement.IndexName)) + { + throw new TableOrIndexAlreadyExistsException("Index Already Exists"); + } + Models.Index b = new Models.Index(createStatement, rootPage); + index.Add(b); + Save_index(this.index); + } + + public bool TryDropStatementForIndex(DropStatement dropStatement) + { + //if the index hasn't been created before, return false + if (!this.If_in(dropStatement.IndexName)) + { + return false; + } + for (int i = 0; i < index.Count;) + { + if (index[i].index_name == dropStatement.IndexName) + { + index.RemoveAt(i); + break; + } + else + i++; + } + Save_index(this.index); + return true; + } + public void DropStatementForIndex(DropStatement dropStatement) + { + //if the index hasn't been created before, return false + if (!this.If_in(dropStatement.IndexName)) + { + throw new TableOrIndexNotExistsException($"Index {dropStatement.IndexName} Not Exists"); + } + for (int i = 0; i < index.Count;) + { + if (index[i].index_name == dropStatement.IndexName) + { + index.RemoveAt(i); + break; + } + else + i++; + } + Save_index(this.index); + } + + public string Of_table(string Indexname) + { + for (int i = 0; i < index.Count; i++) + if (index[i].index_name == Indexname) + return index[i].table_name; + return ""; + } + public void Load_index() + { + if (System.IO.File.Exists($"{_databaseName}.indices.dbcatalog")) + { + using (FileStream fs = new FileStream($"{_databaseName}.indices.dbcatalog", FileMode.Open)) + { + BinaryFormatter bf = new BinaryFormatter(); + this.index = bf.Deserialize(fs) as List; + fs.Close(); + } + } + else + { + this.index = new List(); + } + return; + + } + + public void Save_index(List index) + { + using (FileStream fs = new FileStream($"{_databaseName}.indices.dbcatalog", FileMode.Create)) + { + BinaryFormatter bf = new BinaryFormatter(); + bf.Serialize(fs, index); + fs.Close(); + } + } + public Catalog_index(string databaseName) + { + _databaseName = databaseName; + Load_index();//get table list from the file + } + } +} diff --git a/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs b/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs new file mode 100644 index 0000000..9baa45f --- /dev/null +++ b/src/MiniSQL.CatalogManager/Controllers/Catalog_table.cs @@ -0,0 +1,236 @@ +using System.Collections.Generic; +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; + +namespace MiniSQL.CatalogManager.Controllers +{ + //save all the tables in the table catalog + class Catalog_table + { + private readonly string _databaseName; + public List tables; + + //return the table name 'tableName' + //warning:need to check whether the tableName is in the table catalog first + public Models.Table return_table(string tableName) + { + for (int i = 0; i < tables.Count; i++) + { + if (tables[i].table_name == tableName) + { + return tables[i]; + } + } + //useless but for syntax correctness + return tables[tables.Count - 1]; + } + + //return the schema record of the table named table name + public SchemaRecord GetTableSchemaRecord(string tableName) + { + SchemaRecord s = new SchemaRecord(); + s.Type = SchemaTypes.Table; + s.Name = tableName; + //since this is the table and there is no table that is associated to it + s.AssociatedTable = " "; + + //get the target table first, then get the schema record from the table + Table target_table = return_table(tableName); + s.RootPage = target_table.root_page; + s.SQL = new CreateStatement(); + s.SQL.CreateType = CreateType.Table; + s.SQL.TableName = tableName; + + //there is no index information for a table + s.SQL.IndexName = " "; + s.SQL.AttributeName = " "; + + //get every attribute declaration from the target table + + List temp = new List(); + + for (int i = 0; i < target_table.attribute_list.Count; i++) + { + AttributeDeclaration attribute = new AttributeDeclaration(); + attribute.Type = target_table.attribute_list[i].type; + attribute.CharLimit = target_table.attribute_list[i].length; + attribute.IsUnique = target_table.attribute_list[i].is_unique; + attribute.AttributeName = target_table.attribute_list[i].attribute_name; + temp.Add(attribute); + } + s.SQL.AttributeDeclarations = temp; + + s.SQL.PrimaryKey = target_table.primary_key; + //Console.WriteLine("hhhh"); + return s; + } + + //return the schema record of the table named table name + public List GetTablesSchemaRecord() + { + List list = new List(); + for (int i = 0; i < tables.Count; i++) + { + SchemaRecord target_table = GetTableSchemaRecord(tables[i].table_name); + list.Add(target_table); + } + return list; + } + + //to check if there is such a table named 'name' + //if in,then return true. Vice versa + public bool If_in(string name) + { + for (int i = 0; i < tables.Count; i++) + { + if (tables[i].table_name == name) + { + return true; + } + } + return false; + } + + public void AssertExist(string name) + { + if (!If_in(name)) + throw new TableOrIndexNotExistsException($"Table \"{name}\" not exists"); + } + + public void AssertNotExist(string name) + { + if (If_in(name)) + throw new TableOrIndexAlreadyExistsException($"Table \"{name}\" already exists"); + } + + //update the rootPage of the table named 'name' + //return false if not find + public bool Update(string name, int rootPage) + { + bool has_find = false; + for (int i = 0; i < tables.Count; i++) + { + if (tables[i].table_name == name) + { + tables[i].root_page = rootPage; + has_find = true; + break; + } + } + Save_table(tables); + return has_find; + } + + //try to create one table and save the result into the file + //if succeed, return true + //if the table is already created, return false + public bool TryCreateStatementForTable(CreateStatement createStatement, int rootPage) + { + if (this.If_in(createStatement.TableName)) + { + return false; + } + Models.Table a = new Models.Table(createStatement, rootPage); + tables.Add(a); + Save_table(this.tables); + return true; + } + public void CreateStatementForTable(CreateStatement createStatement, int rootPage) + { + if (this.If_in(createStatement.TableName)) + { + throw new TableOrIndexAlreadyExistsException("Table Already Exists"); + } + Models.Table a = new Models.Table(createStatement, rootPage); + tables.Add(a); + Save_table(this.tables); + } + + //try to drop one table and save the result into the file + //if succeed, return true + //if can't find table, return false + public bool TryDropStatementForTable(DropStatement dropStatement) + { + bool if_find = false; + if (this.If_in(dropStatement.TableName)) + for (int i = 0; i < this.tables.Count;) + { + if (this.tables[i].table_name == dropStatement.TableName) + { + tables.RemoveAt(i); + Save_table(tables); + if_find = true; + } + else + i++; + } + //delete all the indices that are related to the deleted table + Catalog_index b = new Catalog_index(_databaseName); + return if_find && b.DeleteIndicesOfTable(dropStatement.TableName); + } + public void DropStatementForTable(DropStatement dropStatement) + { + bool if_find = false; + if (this.If_in(dropStatement.TableName)) + for (int i = 0; i < this.tables.Count;) + { + if (this.tables[i].table_name == dropStatement.TableName) + { + tables.RemoveAt(i); + Save_table(tables); + if_find = true; + } + else + i++; + } + //delete all the indices that are related to the deleted table + Catalog_index b = new Catalog_index(_databaseName); + if (if_find) + b.DeleteIndicesOfTable(dropStatement.TableName); + else + throw new TableOrIndexNotExistsException($"Table {dropStatement.TableName} Not Exists"); + } + + //load the table from file and store the data into tables + public void Load_table() + { + if (System.IO.File.Exists($"{_databaseName}.tables.dbcatalog")) + { + using (FileStream fs = new FileStream($"{_databaseName}.tables.dbcatalog", FileMode.Open)) + { + BinaryFormatter bf = new BinaryFormatter(); + this.tables = bf.Deserialize(fs) as List; + fs.Close(); + } + } + else + { + this.tables = new List(); + } + return; + } + + //save data of tables into the file + public void Save_table(List tables) + { + using (FileStream fs = new FileStream($"{_databaseName}.tables.dbcatalog", FileMode.Create)) + { + BinaryFormatter bf = new BinaryFormatter(); + bf.Serialize(fs, tables); + fs.Close(); + } + } + + //load the tables from the txt file + public Catalog_table(string databaseName) + { + _databaseName = databaseName; + Load_table(); + } + } + +} diff --git a/src/MiniSQL.CatalogManager/MiniSQL.CatalogManager.csproj b/src/MiniSQL.CatalogManager/MiniSQL.CatalogManager.csproj index ea6c2b7..2100b89 100644 --- a/src/MiniSQL.CatalogManager/MiniSQL.CatalogManager.csproj +++ b/src/MiniSQL.CatalogManager/MiniSQL.CatalogManager.csproj @@ -6,8 +6,8 @@ - Exe - netcoreapp3.1 + + net5.0 diff --git a/src/MiniSQL.CatalogManager/Models/Attribute.cs b/src/MiniSQL.CatalogManager/Models/Attribute.cs new file mode 100644 index 0000000..34621b8 --- /dev/null +++ b/src/MiniSQL.CatalogManager/Models/Attribute.cs @@ -0,0 +1,22 @@ +using System; +using MiniSQL.Library.Models; + +namespace MiniSQL.CatalogManager.Models +{ + + [Serializable] + class Attribute + { + public string attribute_name; + public AttributeTypes type;//three kinds of type: float int char(with limit) + public bool is_unique; + public int length;//the length of string + public Attribute(string attribute_name, AttributeTypes type, bool is_unique, int length) + { + this.attribute_name = attribute_name; + this.type = type; + this.is_unique = is_unique; + this.length = length; + } + } +} diff --git a/src/MiniSQL.CatalogManager/Models/Index.cs b/src/MiniSQL.CatalogManager/Models/Index.cs new file mode 100644 index 0000000..2f6c779 --- /dev/null +++ b/src/MiniSQL.CatalogManager/Models/Index.cs @@ -0,0 +1,24 @@ +using System; +using MiniSQL.Library.Models; + +namespace MiniSQL.CatalogManager.Models +{ + [Serializable] + class Index + { + public string table_name { get; set; } + public string attribute_name; + public string index_name; + public bool is_uniqve; + public int root_page; + public Index(CreateStatement createStatement, int root_page) + { + this.table_name = createStatement.TableName; + this.attribute_name = createStatement.AttributeName; + this.index_name = createStatement.IndexName; + this.is_uniqve = createStatement.IsUnique; + this.root_page = root_page; + + } + } +} diff --git a/src/MiniSQL.CatalogManager/Models/Table.cs b/src/MiniSQL.CatalogManager/Models/Table.cs new file mode 100644 index 0000000..d918342 --- /dev/null +++ b/src/MiniSQL.CatalogManager/Models/Table.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using MiniSQL.Library.Models; + +namespace MiniSQL.CatalogManager.Models +{ + + [Serializable] + class Table + { + public string table_name; + public List attribute_list; + public string primary_key; + public int root_page; + public Table(CreateStatement createStatement, int root_page) + { + this.table_name = createStatement.TableName; + this.primary_key = createStatement.PrimaryKey; + this.root_page = root_page; + List temp = new List(); + //to initialize every attribute of this table + for (int i = 0; i < createStatement.AttributeDeclarations.Count; i++) + { + string AttributeName = createStatement.AttributeDeclarations[i].AttributeName; + bool IsUnique = createStatement.AttributeDeclarations[i].IsUnique; + int Length = createStatement.AttributeDeclarations[i].CharLimit; + AttributeTypes Type = createStatement.AttributeDeclarations[i].Type; + Attribute a = new Attribute(AttributeName, Type, IsUnique, Length); + temp.Add(a); + } + //assign the attribute list to the table + this.attribute_list = temp; + } + //check whether the table has such an attribute + public bool Has_attribute(string attribute_name) + { + bool flag = false; + for (int i = 0; i < attribute_list.Count; i++) + { + if (attribute_list[i].attribute_name == attribute_name) + { + flag = true; + } + } + return flag; + } + + } +} diff --git a/src/MiniSQL.CatalogManager/Program.cs b/src/MiniSQL.CatalogManager/Program.cs index cd2410d..7028a1e 100644 --- a/src/MiniSQL.CatalogManager/Program.cs +++ b/src/MiniSQL.CatalogManager/Program.cs @@ -5,17 +5,18 @@ using MiniSQL.Library.Interfaces; using System.Diagnostics; using System.IO; +using MiniSQL.CatalogManager.Controllers; namespace MiniSQL.CatalogManager { class Program { - static ICatalogManager icatalog = new Catalog(); + static ICatalogManager icatalog = new Catalog("test"); //check if the program can successfully check the validation of each kind of input statement static bool CheckValidation() { //since quitstatement and execfile statement are too simple,we skip them here - Catalog func = new Catalog(); + Catalog func = new Catalog("test"); //select statement //3 kinds, each with a true and a false version @@ -495,8 +496,8 @@ static bool CheckUpdate() static void Main(string[] args) { Console.WriteLine("[CatalogManager] Start!"); - File.Delete("./index.txt"); - File.Delete("./tables.txt"); + File.Delete($"./test.indices.dbcatalog"); + File.Delete($"./test.tables.dbcatalog"); CheckCreate(); CheckUpdate(); CheckGetSchemaRecord(); @@ -516,25 +517,25 @@ private static Expression GetExpression(string name1, string name2, string name3 Expression idExp = new Expression() { Operator = Operator.AtomVariable, AttributeName = name1 }; Expression temp1 = new Expression() { Operator = Operator.AtomConcreteValue, ConcreteValue = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 10 } }; - idOperator.LeftOperant = idExp; - idOperator.RightOperant = temp1; + idOperator.LeftOperand = idExp; + idOperator.RightOperand = temp1; Expression classOperator = new Expression() { Operator = Operator.MoreThan }; Expression classExp = new Expression() { Operator = Operator.AtomVariable, AttributeName = name2 }; Expression temp2 = new Expression() { Operator = Operator.AtomConcreteValue, ConcreteValue = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 10 } }; - classOperator.LeftOperant = temp2; - classOperator.RightOperant = classExp; + classOperator.LeftOperand = temp2; + classOperator.RightOperand = classExp; Expression scoreOperator = new Expression() { Operator = Operator.LessThanOrEqualTo }; Expression scoreExp = new Expression() { Operator = Operator.AtomVariable, AttributeName = name3 }; Expression temp3 = new Expression() { Operator = Operator.AtomConcreteValue, ConcreteValue = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 10 } }; - scoreOperator.LeftOperant = temp3; - scoreOperator.RightOperant = scoreExp; + scoreOperator.LeftOperand = temp3; + scoreOperator.RightOperand = scoreExp; // connect tree trunk - root.LeftOperant = secondAnd; - root.RightOperant = scoreOperator; - secondAnd.LeftOperant = idOperator; - secondAnd.RightOperant = classOperator; + root.LeftOperand = secondAnd; + root.RightOperand = scoreOperator; + secondAnd.LeftOperand = idOperator; + secondAnd.RightOperand = classOperator; return root; } diff --git a/src/MiniSQL.Api/Controllers/View.cs b/src/MiniSQL.Client/Controllers/View.cs similarity index 68% rename from src/MiniSQL.Api/Controllers/View.cs rename to src/MiniSQL.Client/Controllers/View.cs index 2144863..0648862 100644 --- a/src/MiniSQL.Api/Controllers/View.cs +++ b/src/MiniSQL.Client/Controllers/View.cs @@ -2,44 +2,27 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; -using MiniSQL.BufferManager.Controllers; -using MiniSQL.CatalogManager; -using MiniSQL.IndexManager.Interfaces; -using MiniSQL.Interpreter; +using System.Text.RegularExpressions; +using MiniSQL.Client.Helpers; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; -using MiniSQL.RecordManager; -namespace MiniSQL.Api.Controllers +namespace MiniSQL.Client.Controllers { public class View { - private readonly IIndexManager _bTreeController; - private readonly IInterpreter _interpreter; - private readonly ICatalogManager _catalogManager; - private readonly IRecordManager _recordManager; - private readonly IApi _api; - private readonly Pager _pager; + private readonly IApi _databaseController; private bool isCtrlC = false; - public View(IIndexManager bTreeController, IInterpreter interpreter, ICatalogManager catalogManager, IRecordManager recordManager, IApi api, Pager pager) + public View(IApi databaseController) { - // ensure writing back when ctrl-c - Console.CancelKeyPress += OnExit; - // print prologue Console.WriteLine(); Console.WriteLine("Hello MiniSQL!"); Console.WriteLine(); - - // init - _pager = pager; - _bTreeController = bTreeController; - _interpreter = interpreter; - _catalogManager = catalogManager; - // IIndexManager indexManager = new IndexManager(); - _recordManager = recordManager; - _api = api; + + _databaseController = databaseController; } // interactive(blocking) view of the whole solution @@ -61,21 +44,50 @@ public void Interactive() string line = Console.ReadLine(); // restore the previous color Console.ForegroundColor = defaultColor; - input.Append(line); // ctrl-c pressed if (line == null) { return; } - // exit when "exit" - if (line == "exit") + // exit when "exit" or "quit" or "exit;" or "exit ;" or "exit; ;;; ;" + if (Regex.IsMatch(line, @"^(?i)\s*(exit|quit)\s*(;\s*)*(?-i)$")) { isExit = true; continue; } + // use database + if (Regex.IsMatch(line, @"^(?i)\s*use\s*database\s*\S+?\s*(;\s*)*(?-i)$")) + { + string databaseName = line.Split(new string[] { " ", "\n" }, StringSplitOptions.RemoveEmptyEntries)[2].TrimEnd(';'); + _databaseController.ChangeContext(databaseName); + continue; + } + // drop database + if (Regex.IsMatch(line, @"^(?i)\s*drop\s*database\s*\S+?\s*(;\s*)*(?-i)$")) + { + string databaseName = line.Split(new string[] { " ", "\n" }, StringSplitOptions.RemoveEmptyEntries)[2].TrimEnd(';'); + _databaseController.DropDatabase(databaseName); + continue; + } + if (!_databaseController.IsUsingDatabase) + { + // WORKAROUND + Console.WriteLine("[Error] No database in use"); + continue; + } + // flush all the dirty pages back to secondary memory and clean the main memory out of any page + // "flush" or "flush;" or "flush ;" or "flush;; ;; ; " + if (Regex.IsMatch(line, @"^(?i)\s*(flush)\s*(;\s*)*(?-i)$")) + { + _databaseController.FlushPages(); + continue; + } + input.Append(line); // perform SQL for each input when the last line ends with ';' if (!line.TrimEnd().EndsWith(";")) { + // compensate '\n' + input.Append("\n"); continue; } // execute SQL @@ -83,7 +95,7 @@ public void Interactive() stopwatch.Start(); try { - List selectResults = _api.Query(input.ToString()); + List selectResults = _databaseController.Query(input.ToString()); // print results for select statement foreach (var selectResult in selectResults) { @@ -95,7 +107,7 @@ public void Interactive() { Console.WriteLine($"[Error] {ex.Message}"); } - catch (KeyNotExistException ex) + catch (KeyNotExistsException ex) { Console.WriteLine($"[Error] {ex.Message}"); } @@ -103,6 +115,26 @@ public void Interactive() { Console.WriteLine($"[Error] {ex.Message}"); } + catch (TableOrIndexAlreadyExistsException ex) + { + Console.WriteLine($"[Error] {ex.Message}"); + } + catch (TableOrIndexNotExistsException ex) + { + Console.WriteLine($"[Error] {ex.Message}"); + } + catch (AttributeNotExistsException ex) + { + Console.WriteLine($"[Error] {ex.Message}"); + } + catch (NumberOfAttributesNotMatchsException ex) + { + Console.WriteLine($"[Error] {ex.Message}"); + } + catch (TypeOfAttributeNotMatchsException ex) + { + Console.WriteLine($"[Error] {ex.Message}"); + } stopwatch.Stop(); // print time consumed defaultColor = Console.ForegroundColor; @@ -113,14 +145,8 @@ public void Interactive() input.Clear(); } // save database file - _pager.Close(); - } - - // BUG: NOT WORKING - private void OnExit(object sender, EventArgs e) - { - isCtrlC = true; - _pager.Close(); + if (_databaseController.IsUsingDatabase) + _databaseController.ClosePager(); } private static void PrintRows(SelectResult result) @@ -137,7 +163,7 @@ private static void PrintRows(SelectResult result) string format = "{0, " + (-sizes[columnIndex]).ToString() + "}"; Console.Write($" {string.Format(format, name.AttributeName)} "); if (columnIndex < result.ColumnDeclarations.Count - 1) - Print("|", ConsoleColor.DarkGray); + PrintHelper.Print("|", ConsoleColor.DarkGray); columnIndex++; } Console.WriteLine(); @@ -167,7 +193,7 @@ private static void PrintRows(SelectResult result) } Console.Write($" {string.Format(format, stringToPrint)} "); if (columnIndex < row.Count - 1) - Print("|", ConsoleColor.DarkGray); + PrintHelper.Print("|", ConsoleColor.DarkGray); columnIndex++; } Console.WriteLine(); @@ -211,16 +237,5 @@ private static List GetColumnSize(SelectResult result) } return sizes; } - - private static void Print(string toPrint, ConsoleColor color) - { - // change color - ConsoleColor defaultColor = Console.ForegroundColor; - Console.ForegroundColor = color; - // print - Console.Write(toPrint); - // restore the previous color - Console.ForegroundColor = defaultColor; - } } -} \ No newline at end of file +} diff --git a/src/MiniSQL.Client/Helpers/PrintHelper.cs b/src/MiniSQL.Client/Helpers/PrintHelper.cs new file mode 100644 index 0000000..a5d8827 --- /dev/null +++ b/src/MiniSQL.Client/Helpers/PrintHelper.cs @@ -0,0 +1,18 @@ +using System; + +namespace MiniSQL.Client.Helpers +{ + public static class PrintHelper + { + public static void Print(string toPrint, ConsoleColor color) + { + // change color + ConsoleColor defaultColor = Console.ForegroundColor; + Console.ForegroundColor = color; + // print + Console.Write(toPrint); + // restore the previous color + Console.ForegroundColor = defaultColor; + } + } +} diff --git a/src/MiniSQL.Client/MiniSQL.Client.csproj b/src/MiniSQL.Client/MiniSQL.Client.csproj new file mode 100644 index 0000000..d04b912 --- /dev/null +++ b/src/MiniSQL.Client/MiniSQL.Client.csproj @@ -0,0 +1,17 @@ + + + + + + + + + + + + + Exe + net5.0 + + + diff --git a/src/MiniSQL.Client/Program.cs b/src/MiniSQL.Client/Program.cs new file mode 100644 index 0000000..bfa7e17 --- /dev/null +++ b/src/MiniSQL.Client/Program.cs @@ -0,0 +1,17 @@ +using MiniSQL.Api.Controllers; +using MiniSQL.Library.Interfaces; +using MiniSQL.Client.Controllers; + +namespace MiniSQL.Client +{ + class Program + { + static void Main(string[] args) + { + DatabaseBuilder builder = new DatabaseBuilder(); + IApi controller = new ApiController(builder); + View view = new View(controller); + view.Interactive(); + } + } +} diff --git a/src/MiniSQL.Api/tests/1_insert_large_data.sql b/src/MiniSQL.Client/tests/1_insert_large_data.sql similarity index 100% rename from src/MiniSQL.Api/tests/1_insert_large_data.sql rename to src/MiniSQL.Client/tests/1_insert_large_data.sql diff --git a/src/MiniSQL.Client/tests/compilation.sql b/src/MiniSQL.Client/tests/compilation.sql new file mode 100644 index 0000000..2ccf492 --- /dev/null +++ b/src/MiniSQL.Client/tests/compilation.sql @@ -0,0 +1,83 @@ +-- insert-delete + +-- create table test +-- ( +-- id INT, +-- name Char(8) +-- ); +create table test +( + id INT, + name Char(8), + primary key (id) +); + +insert into test values (1, "Tom"); +insert into test values (2, "Tim"); +insert into test values (3, "Tai"); + +select * from test; + +delete from test where name = "Tai"; + +select * from test; + +delete from test where id < 3; + +select * from test; + +-- type + +create table typetest +( + id INT, + name Char(8), + height FLOAT, + primary key (id) +); + +insert into typetest values (3, "test1", 12.3); +insert into typetest values (3, "test2", 332.1); + +select * from typetest; + +-- table collision + +create table test +( + id INT, + name Char(8), + height FLOAT, + primary key (id) +); +create table test +( + id INT, + name Char(8), + height FLOAT, + primary key (id) +); + +-- inconsistent number of values + +create table test +( + id INT, + name Char(8), + height FLOAT, + primary key (id) +); + +insert into test values (1, "Tom"); + +-- inconsistent types of values + +create table test +( + id INT, + name Char(8), + height FLOAT, + primary key (id) +); + +insert into test values (1, 1123.4, "Tom"); diff --git a/src/MiniSQL.Api/tests/index-create-delete-0.sql b/src/MiniSQL.Client/tests/index-create-delete-0.sql similarity index 100% rename from src/MiniSQL.Api/tests/index-create-delete-0.sql rename to src/MiniSQL.Client/tests/index-create-delete-0.sql diff --git a/src/MiniSQL.Api/tests/index-create-delete-1.sql b/src/MiniSQL.Client/tests/index-create-delete-1.sql similarity index 100% rename from src/MiniSQL.Api/tests/index-create-delete-1.sql rename to src/MiniSQL.Client/tests/index-create-delete-1.sql diff --git a/src/MiniSQL.Api/tests/index-create-delete-2.sql b/src/MiniSQL.Client/tests/index-create-delete-2.sql similarity index 100% rename from src/MiniSQL.Api/tests/index-create-delete-2.sql rename to src/MiniSQL.Client/tests/index-create-delete-2.sql diff --git a/src/MiniSQL.Api/tests/table-create-drop-0.sql b/src/MiniSQL.Client/tests/table-create-drop-0.sql similarity index 100% rename from src/MiniSQL.Api/tests/table-create-drop-0.sql rename to src/MiniSQL.Client/tests/table-create-drop-0.sql diff --git a/src/MiniSQL.Client/tests/table-create-drop-1.sql b/src/MiniSQL.Client/tests/table-create-drop-1.sql new file mode 100644 index 0000000..91e3712 --- /dev/null +++ b/src/MiniSQL.Client/tests/table-create-drop-1.sql @@ -0,0 +1,21 @@ +-- create table person ( +-- pid int primary key, +-- name char(32), +-- identity int, +-- age int, +-- height float, +-- weight float, +-- address char(128) +-- ); +create table person ( + pid int, + name char(32), + identity int, + age int, + height float, + weight float, + address char(128), + primary key (pid) +); + +drop table person; diff --git a/src/MiniSQL.Api/tests/table-create-drop-2.sql b/src/MiniSQL.Client/tests/table-create-drop-2.sql similarity index 100% rename from src/MiniSQL.Api/tests/table-create-drop-2.sql rename to src/MiniSQL.Client/tests/table-create-drop-2.sql diff --git a/src/MiniSQL.Api/tests/table-insert-delete-0.sql b/src/MiniSQL.Client/tests/table-insert-delete-0.sql similarity index 100% rename from src/MiniSQL.Api/tests/table-insert-delete-0.sql rename to src/MiniSQL.Client/tests/table-insert-delete-0.sql diff --git a/src/MiniSQL.Api/tests/table-insert-delete-1.sql b/src/MiniSQL.Client/tests/table-insert-delete-1.sql similarity index 100% rename from src/MiniSQL.Api/tests/table-insert-delete-1.sql rename to src/MiniSQL.Client/tests/table-insert-delete-1.sql diff --git a/src/MiniSQL.Api/tests/table-select-0.sql b/src/MiniSQL.Client/tests/table-select-0.sql similarity index 100% rename from src/MiniSQL.Api/tests/table-select-0.sql rename to src/MiniSQL.Client/tests/table-select-0.sql diff --git a/src/MiniSQL.Api/tests/table-select-1.sql b/src/MiniSQL.Client/tests/table-select-1.sql similarity index 100% rename from src/MiniSQL.Api/tests/table-select-1.sql rename to src/MiniSQL.Client/tests/table-select-1.sql diff --git a/src/MiniSQL.Api/tests/test-1000.sql b/src/MiniSQL.Client/tests/test-1000.sql similarity index 100% rename from src/MiniSQL.Api/tests/test-1000.sql rename to src/MiniSQL.Client/tests/test-1000.sql diff --git a/src/MiniSQL.Api/tests/test-10w.sql b/src/MiniSQL.Client/tests/test-10w.sql similarity index 100% rename from src/MiniSQL.Api/tests/test-10w.sql rename to src/MiniSQL.Client/tests/test-10w.sql diff --git a/src/MiniSQL.Api/tests/test-1w.sql b/src/MiniSQL.Client/tests/test-1w.sql similarity index 100% rename from src/MiniSQL.Api/tests/test-1w.sql rename to src/MiniSQL.Client/tests/test-1w.sql diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.Create.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.Create.cs new file mode 100644 index 0000000..10117cd --- /dev/null +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.Create.cs @@ -0,0 +1,13 @@ +using MiniSQL.IndexManager.Models; + +namespace MiniSQL.IndexManager.Controllers +{ + public partial class BTreeController + { + public BTreeNode OccupyNewTableNode() + { + BTreeNode newNode = GetNewNode(PageTypes.LeafTablePage); + return newNode; + } + } +} diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.Delete.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.Delete.cs new file mode 100644 index 0000000..4abc191 --- /dev/null +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.Delete.cs @@ -0,0 +1,315 @@ +using System; +using System.Collections.Generic; +using MiniSQL.BufferManager.Models; +using MiniSQL.IndexManager.Models; +using MiniSQL.Library.Exceptions; +using MiniSQL.Library.Models; + +namespace MiniSQL.IndexManager.Controllers +{ + public partial class BTreeController + { + public BTreeNode DeleteCells(BTreeNode root, Expression expression, string keyName, List attributeDeclarations) + { + List nodesTobeDeleted = FindCells(root, expression, keyName, attributeDeclarations); + foreach (var cell in nodesTobeDeleted) + { + root = Delete(cell, root); + } + return root; + } + + public BTreeNode Delete(DBRecord key, BTreeNode Root) + { + BTreeNode NodeTobeDeleted = FindNode(key, Root); + if (NodeTobeDeleted == null) + { + throw new KeyNotExistsException("Cannot find the key!"); + } + return Delete_entry(NodeTobeDeleted, key, Root); + } + + public BTreeNode Delete(BTreeCell keyCell, BTreeNode Root) + { + DBRecord key = keyCell.Key; + return Delete(key, Root); + } + + private BTreeNode Delete_leaf_redistri(BTreeNode NodetobeDeleted, DBRecord key, BTreeNode Root) + { + BTreeCell cell; + UInt16 offset; + int indexInOffsetArray; + + MemoryPage parentPage = _pager.ReadPage((int)NodetobeDeleted.ParentPage); + BTreeNode parentNode = new BTreeNode(parentPage); + + (cell, offset, indexInOffsetArray) = parentNode.FindBTreeCell(key); + //the deleted node is not on the right page of parentNode + if (cell != null) + { + MemoryPage brotherPage = _pager.ReadPage((int)NodetobeDeleted.RightPage); + BTreeNode brotherNode = new BTreeNode(brotherPage); + //If there is a node on the left of the deleted node,it need to be connected to the brother node. + if (indexInOffsetArray>= 1) + { + InternalTableCell leftNodeCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[indexInOffsetArray - 1]); + MemoryPage leftPage = _pager.ReadPage((int)leftNodeCell.ChildPage); + BTreeNode leftNode = new BTreeNode(leftPage); + leftNode.RightPage = (uint)brotherNode.RawPage.PageNumber; + } + + if (brotherNode.NumCells + NodetobeDeleted.NumCells <= MaxCell) //merge + { + //After the merge,one cell in the parentNode will be deleted + parentNode.DeleteBTreeCell(cell); + //merge two node + for (int i = 0; i < NodetobeDeleted.NumCells; i++) + { + brotherNode.InsertBTreeCell(NodetobeDeleted.GetBTreeCell(NodetobeDeleted.CellOffsetArray[i])); + } + DeleteNode(NodetobeDeleted); + + } + else //redistribute + { + BTreeCell movedCell = brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[0]); + DBRecord newKey = brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[1]).Key; + + NodetobeDeleted.InsertBTreeCell(movedCell); + brotherNode.DeleteBTreeCell(movedCell); + + BTreeCell parent_Cell; + UInt16 parent_offset; + int parent_indexInOffsetArray; + (parent_Cell, parent_offset, parent_indexInOffsetArray) = parentNode.FindBTreeCell(key); + + InternalTableCell newCell = new InternalTableCell(newKey, (uint)NodetobeDeleted.RawPage.PageNumber); + parentNode.DeleteBTreeCell(parent_Cell); + parentNode.InsertBTreeCell(newCell); + + } + } + //The node to be deleted is on the rightpage,the brother node is on the left + else + { + InternalTableCell brotherCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1]); + MemoryPage brotherPage = _pager.ReadPage((int)brotherCell.ChildPage); + BTreeNode brotherNode = new BTreeNode(brotherPage); + + //The right page of brother node should be 0 + + brotherNode.RightPage = NodetobeDeleted.RightPage; + + if (brotherNode.NumCells + NodetobeDeleted.NumCells <= MaxCell) //merge + { + //After the merge,one cell in the parentNode will be deleted + parentNode.DeleteBTreeCell(brotherCell); + //merge two node + for (int i = 0; i < NodetobeDeleted.NumCells; i++) + { + brotherNode.InsertBTreeCell(NodetobeDeleted.GetBTreeCell(NodetobeDeleted.CellOffsetArray[i])); + } + DeleteNode(NodetobeDeleted); + parentNode.RightPage = (uint)brotherNode.RawPage.PageNumber; + + } + else //redistribute + { + BTreeCell movedCell = brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[brotherNode.NumCells - 1]); + DBRecord newKey = movedCell.Key; + + NodetobeDeleted.InsertBTreeCell(movedCell); + brotherNode.DeleteBTreeCell(movedCell); + + BTreeCell parent_Cell; + UInt16 parent_offset; + int parent_indexInOffsetArray; + (parent_Cell, parent_offset, parent_indexInOffsetArray) = parentNode.FindBTreeCell(key); + + InternalTableCell newCell = new InternalTableCell(newKey, (uint)NodetobeDeleted.RawPage.PageNumber); + parentNode.DeleteBTreeCell(parent_Cell); + parentNode.InsertBTreeCell(newCell); + + } + + } + + + NodetobeDeleted = parentNode; + //deal with parent Nodes + return Delete_internal_redistribute(NodetobeDeleted, key, Root); + } + + private BTreeNode Delete_internal_redistribute(BTreeNode NodetobeDeleted, DBRecord key, BTreeNode Root) + { + InternalTableCell tmpCell; + MemoryPage tmpPage; + BTreeNode tmpNode; + + BTreeCell cell; + UInt16 offset; + int indexInOffsetArray; + + MemoryPage parentPage = null; + BTreeNode parentNode = null; + + while (NodetobeDeleted.NumCells < (MaxCell + 1) / 2) + { + //The root + if (NodetobeDeleted.ParentPage == 0) + { + if (NodetobeDeleted.NumCells == 0) + { + MemoryPage NewRootPage = _pager.ReadPage((int)NodetobeDeleted.RightPage); + BTreeNode newRoot = new BTreeNode(NewRootPage); + newRoot.ParentPage = 0; + return newRoot; + } + return Root; + } + else + { + parentPage = _pager.ReadPage((int)NodetobeDeleted.ParentPage); + parentNode = new BTreeNode(parentPage); + (cell, offset, indexInOffsetArray) = parentNode.FindBTreeCell(key); + //The node to be deleted isn't on the rightpage + if (cell != null) + { + InternalTableCell brotherCell = null; + MemoryPage brotherPage = null; + BTreeNode brotherNode = null; + //if the right brother is on rightpage + if (indexInOffsetArray + 1 == parentNode.NumCells) + { + brotherPage = _pager.ReadPage((int)parentNode.RightPage); + brotherNode = new BTreeNode(brotherPage); + + } + else + { + brotherCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[indexInOffsetArray + 1]); + brotherPage = _pager.ReadPage((int)brotherCell.ChildPage); + brotherNode = new BTreeNode(brotherPage); + } + //merge + if (brotherNode.NumCells + NodetobeDeleted.NumCells < MaxCell) + { + for (int i = 0; i < NodetobeDeleted.NumCells; i++) + { + tmpCell = (InternalTableCell)NodetobeDeleted.GetBTreeCell(NodetobeDeleted.CellOffsetArray[i]); + + brotherNode.InsertBTreeCell(tmpCell); + + tmpPage = _pager.ReadPage((int)tmpCell.ChildPage); + tmpNode = new BTreeNode(tmpPage); + tmpNode.ParentPage = (uint)brotherNode.RawPage.PageNumber; + } + //move the cell in parentNode to brotherNode + InternalTableCell insertCell = new InternalTableCell(cell.Key, (uint)NodetobeDeleted.RightPage); + brotherNode.InsertBTreeCell(insertCell); + tmpPage = _pager.ReadPage((int)insertCell.ChildPage); + tmpNode = new BTreeNode(tmpPage); + tmpNode.ParentPage = (uint)brotherNode.RawPage.PageNumber; + + DeleteNode(NodetobeDeleted); + parentNode.DeleteBTreeCell(cell); + } + //redistribute + else + { + InternalTableCell movedCell = (InternalTableCell)brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[0]); + DBRecord upperKey = movedCell.Key; + DBRecord downKey = cell.Key; + + InternalTableCell insertDeletedCell = new InternalTableCell(downKey, (uint)NodetobeDeleted.RightPage); + NodetobeDeleted.InsertBTreeCell(insertDeletedCell); + NodetobeDeleted.RightPage = movedCell.ChildPage; + + tmpPage = _pager.ReadPage((int)movedCell.ChildPage); + tmpNode = new BTreeNode(tmpPage); + tmpNode.ParentPage = (uint)NodetobeDeleted.RawPage.PageNumber; + + InternalTableCell insertParentCell = new InternalTableCell(upperKey, (uint)NodetobeDeleted.RawPage.PageNumber); + parentNode.DeleteBTreeCell(cell); + parentNode.InsertBTreeCell(insertParentCell); + brotherNode.DeleteBTreeCell(movedCell); + + } + + } + //The node to be deleted is on the rightpage + else + { + InternalTableCell brotherCell = null; + MemoryPage brotherPage = null; + BTreeNode brotherNode = null; + + brotherCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1]); + brotherPage = _pager.ReadPage((int)brotherCell.ChildPage); + brotherNode = new BTreeNode(brotherPage); + //merge + if (brotherNode.NumCells + NodetobeDeleted.NumCells < MaxCell) + { + for (int i = 0; i < brotherNode.NumCells; i++) + { + tmpCell = (InternalTableCell)brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[i]); + + NodetobeDeleted.InsertBTreeCell(tmpCell); + + tmpPage = _pager.ReadPage((int)tmpCell.ChildPage); + tmpNode = new BTreeNode(tmpPage); + tmpNode.ParentPage = (uint)NodetobeDeleted.RawPage.PageNumber; + } + //move the cell in parentNode to brotherNode + InternalTableCell insertCell = new InternalTableCell(brotherCell.Key, (uint)brotherNode.RightPage); + NodetobeDeleted.InsertBTreeCell(insertCell); + tmpPage = _pager.ReadPage((int)insertCell.ChildPage); + tmpNode = new BTreeNode(tmpPage); + tmpNode.ParentPage = (uint)NodetobeDeleted.RawPage.PageNumber; + + DeleteNode(brotherNode); + parentNode.DeleteBTreeCell(parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1])); + } + //redistribute + else + { + DBRecord downKey = parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1]).Key; + InternalTableCell insertDeletedCell = new InternalTableCell(downKey, brotherNode.RightPage); + NodetobeDeleted.InsertBTreeCell(insertDeletedCell); + + + InternalTableCell movedCell = (InternalTableCell)brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[brotherNode.NumCells - 1]); + brotherNode.RightPage = movedCell.ChildPage; + DBRecord upperKey = movedCell.Key; + InternalTableCell insertParentCell = new InternalTableCell(upperKey, (uint)brotherNode.RawPage.PageNumber); + parentNode.InsertBTreeCell(insertParentCell); + brotherNode.DeleteBTreeCell(movedCell); + + tmpPage = _pager.ReadPage((int)brotherNode.RightPage); + tmpNode = new BTreeNode(tmpPage); + tmpNode.ParentPage = (uint)brotherNode.RawPage.PageNumber; + } + } + } + NodetobeDeleted = parentNode; + } + return Root; + } + + private BTreeNode Delete_entry(BTreeNode NodetobeDeleted, DBRecord key, BTreeNode Root) + { + BTreeCell cell; + UInt16 offset; + int indexInOffsetArray; + (cell, offset, indexInOffsetArray) = NodetobeDeleted.FindBTreeCell(key, false); + NodetobeDeleted.DeleteBTreeCell(cell); + + if (NodetobeDeleted.NumCells < MaxCell / 2 && NodetobeDeleted.ParentPage != 0) + { + return Delete_leaf_redistri(NodetobeDeleted, key, Root); + } + return Root; + } + } +} diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.Drop.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.Drop.cs new file mode 100644 index 0000000..2f4b408 --- /dev/null +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.Drop.cs @@ -0,0 +1,40 @@ +using MiniSQL.BufferManager.Models; +using MiniSQL.IndexManager.Models; + +namespace MiniSQL.IndexManager.Controllers +{ + public partial class BTreeController + { + public void RemoveTree(BTreeNode root) + { + if (root.PageType == PageTypes.LeafIndexPage || root.PageType == PageTypes.LeafTablePage) + { + DeleteNode(root); + return; + } + if (root.PageType == PageTypes.InternalIndexPage) + { + foreach (BTreeCell cell in root) + { + MemoryPage page = _pager.ReadPage((int)((InternalIndexCell)cell).ChildPage); + BTreeNode node = new BTreeNode(page); + RemoveTree(node); + } + } + else // (root.PageType == PageTypes.InternalTablePage) + { + foreach (BTreeCell cell in root) + { + MemoryPage page = _pager.ReadPage((int)((InternalTableCell)cell).ChildPage); + BTreeNode node = new BTreeNode(page); + RemoveTree(node); + } + } + MemoryPage rightPage = _pager.ReadPage((int)root.RightPage); + BTreeNode rightNode = new BTreeNode(rightPage); + RemoveTree(rightNode); + // post-order traversal + DeleteNode(root); + } + } +} diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.Find.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.Find.cs new file mode 100644 index 0000000..f60786e --- /dev/null +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.Find.cs @@ -0,0 +1,345 @@ +using System; +using System.Collections.Generic; +using MiniSQL.BufferManager.Models; +using MiniSQL.IndexManager.Models; +using MiniSQL.IndexManager.Utilities; +using MiniSQL.Library.Models; + +namespace MiniSQL.IndexManager.Controllers +{ + public partial class BTreeController + { + /// + /// Search the leaf nodes linearly. + /// + /// the root node of the B+ tree + /// + public IEnumerable LinearSearch(BTreeNode root) + { + BTreeNode startNode = FindMin(root); + while (true) + { + foreach (var cell in startNode) + { + yield return cell; + } + if (startNode.RightPage == 0) + { + break; + } + startNode = BTreeNodeHelper.GetBTreeNode(_pager, (int)startNode.RightPage); + } + } + + public BTreeCell FindCell(DBRecord key, BTreeNode root) + { + BTreeNode child; + BTreeCell cell; + UInt16 offset; + if (root.PageType == PageTypes.LeafTablePage) + { + (cell, _, _) = root.FindBTreeCell(key, false); + return cell; + } + + // If it's internal node + (cell, offset, _) = root.FindBTreeCell(key); + MemoryPage nextpage; + if (offset == 0) //rightpage + { + nextpage = _pager.ReadPage((int)root.RightPage); + child = new BTreeNode(nextpage); + } + else + { + InternalTableCell internalTableCell = (InternalTableCell)cell; + nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); + child = new BTreeNode(nextpage); + } + return FindCell(key, child); + } + + // `keyName` := primary key in table tree; indexed value in index tree + public List FindCells(BTreeNode root, Expression condition, string keyName, List attributeDeclarations) + { + if (condition == null) + { + return LinearSearch(root, condition, attributeDeclarations); + } + else if (condition.SimpleMinterms.ContainsKey(keyName)) + { + List result = new List(); + List values = new List(); + BTreeNode startNode; + + BTreeCell cell; + int startIndexOfCellInStartNode; + + AtomValue bound = condition.SimpleMinterms[keyName].RightOperand.ConcreteValue; + + values.Add(bound); + DBRecord keyFind = new DBRecord(values); + switch (condition.SimpleMinterms[keyName].Operator) + { + case Operator.NotEqual: + return LinearSearch(root, condition, attributeDeclarations); + + case Operator.Equal: + LeafTableCell tmpCell = (LeafTableCell)FindCell(keyFind, root); + if (tmpCell == null) + { + break; + } + else if (condition.Calculate(attributeDeclarations, tmpCell.DBRecord.GetValues()).BooleanValue == true) + { + result.Add(tmpCell); + } + break; + + case Operator.LessThan: + startNode = FindMin(root); + return FindCells(startNode, condition, attributeDeclarations, bound, false); + case Operator.LessThanOrEqualTo: + startNode = FindMin(root); + return FindCells(startNode, condition, attributeDeclarations, bound, true); + case Operator.MoreThan: + startNode = FindNode(keyFind, root, true); + // nothing is equal or more than the value of `keyFind` in the tree + if (startNode == null) + { + return result; + } + (cell, _, startIndexOfCellInStartNode) = startNode.FindBTreeCell(keyFind); + // 2 possible situations for `cell == null`: + // 1: The `keyFind` is bigger than all the key in `startNode` + // 2: The `keyFind` is just between the bigest one in `startNode` and the smallest one in next node + if (cell == null) + { + if (startNode.RightPage == 0) + { + return result; + } + else + { + startIndexOfCellInStartNode = 0; + MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); + startNode = new BTreeNode(nextpage); + } + } + return FindCells(startNode, startIndexOfCellInStartNode, condition, attributeDeclarations, false); + case Operator.MoreThanOrEqualTo: + startNode = FindNode(keyFind, root, true); + // nothing is equal or more than the value of `keyFind` in the tree + if (startNode == null) + { + return result; + } + (cell, _, startIndexOfCellInStartNode) = startNode.FindBTreeCell(keyFind); + if (cell == null) + { + if (startNode.RightPage == 0) + { + return result; + } + else + { + startIndexOfCellInStartNode = 0; + MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); + startNode = new BTreeNode(nextpage); + } + } + return FindCells(startNode, startIndexOfCellInStartNode, condition, attributeDeclarations, true); + default: + throw new Exception("The Operand is not supported!"); + } + //This step may not need? + return result; + } + else + { + return LinearSearch(root, condition, attributeDeclarations); + } + } + + // find the minimal node (leftest leaf node) from the given tree of root node `root` + private BTreeNode FindMin(BTreeNode root) + { + BTreeNode child; + InternalTableCell childCell; + + if (root.PageType == PageTypes.LeafTablePage) + { + return root; + } + // childCell = (InternalTableCell)root.GetBTreeCell(root.CellOffsetArray[0]); + childCell = (InternalTableCell)root[0]; + MemoryPage nextpage = _pager.ReadPage((int)childCell.ChildPage); + child = new BTreeNode(nextpage); + + return FindMin(child); + } + + /// + /// + /// to find cells that satisfy: + /// - starting from `startNode` + /// - ends in `upperBound` + /// - might be inclusive depending on `isIncludeUpperBound` + /// - satisfying `condition` + /// + /// `attributeDeclarations` := the names of the columns + /// + /// + /// + /// the names of the columns + /// + /// + /// + private List FindCells(BTreeNode startNode, Expression condition, List attributeDeclarations, AtomValue upperBound, bool isIncludeUpperBound) + { + List result = new List(); + LeafTableCell leafCell; + + while (true) + { + foreach (var cell in startNode) + { + if (((cell.Key.GetValues()[0]> upperBound).BooleanValue && isIncludeUpperBound) || + ((cell.Key.GetValues()[0]>= upperBound).BooleanValue && !isIncludeUpperBound)) + { + return result; + } + leafCell = (LeafTableCell)cell; + + if (condition.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) + { + result.Add(cell); + } + } + if (startNode.RightPage == 0) + { + return result; + } + MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); + startNode = new BTreeNode(nextpage); + } + } + + /// + /// + /// to find cells that satisfy: + /// - starting from `startIndexOfCell` in `startNode` + /// - `startIndexOfCell` might be inclusive depending on `isIncludeStartCell` + /// - till to the end of the leaf nodes + /// - satisfying `condition` + /// + /// `attributeDeclarations` := the names of the columns + /// + /// + /// + /// + /// the names of the columns + /// + /// + private List FindCells(BTreeNode startNode, int startIndexOfCell, Expression condition, List attributeDeclarations, bool isIncludeStartCell) + { + List result = new List(); + LeafTableCell leafCell; + + if (isIncludeStartCell) + { + // leafCell = (LeafTableCell)startNode.GetBTreeCell(startNode.CellOffsetArray[startIndexOfCell]); + leafCell = (LeafTableCell)startNode[startIndexOfCell]; + if (condition.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) + { + result.Add(leafCell); + } + } + for (int i = startIndexOfCell + 1; i < startNode.NumCells; i++) + { + // leafCell = (LeafTableCell)startNode.GetBTreeCell(startNode.CellOffsetArray[i]); + leafCell = (LeafTableCell)startNode[i]; + if (condition.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) + { + result.Add(leafCell); + } + } + while (startNode.RightPage != 0) + { + MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); + startNode = new BTreeNode(nextpage); + + foreach (var cell in startNode) + { + leafCell = (LeafTableCell)cell; + if (condition.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) + { + result.Add(cell); + } + } + } + return result; + } + + // if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + private BTreeNode FindNode(DBRecord key, BTreeNode root, bool isFuzzySearch = false) + { + BTreeNode child; + BTreeCell cell; + UInt16 offset; + if (root.PageType == PageTypes.LeafTablePage) + { + (cell, _, _) = root.FindBTreeCell(key, isFuzzySearch); + if (cell != null) + return root; + else + return null; + } + + //If it's internal node + (cell, offset, _) = root.FindBTreeCell(key); + MemoryPage nextpage; + if (offset == 0) //rightpage + { + nextpage = _pager.ReadPage((int)root.RightPage); + child = new BTreeNode(nextpage); + } + else + { + InternalTableCell internalTableCell = (InternalTableCell)cell; + nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); + child = new BTreeNode(nextpage); + } + return FindNode(key, child); + } + + private List LinearSearch(BTreeNode root, Expression expression, List attributeDeclarations) + { + BTreeNode startNode = FindMin(root); + List result = new List(); + LeafTableCell leafCell; + + while (true) + { + foreach (var cell in startNode) + { + leafCell = (LeafTableCell)cell; + if (expression == null) + { + result.Add(cell); + } + else if (expression.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) + { + result.Add(cell); + } + } + if (startNode.RightPage == 0) + { + return result; + } + MemoryPage nextpage = _pager.ReadPage((int)startNode.RightPage); + startNode = new BTreeNode(nextpage); + } + } + } +} diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.Insert.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.Insert.cs new file mode 100644 index 0000000..6090a51 --- /dev/null +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.Insert.cs @@ -0,0 +1,207 @@ +using System; +using MiniSQL.BufferManager.Models; +using MiniSQL.IndexManager.Models; +using MiniSQL.Library.Exceptions; + +namespace MiniSQL.IndexManager.Controllers +{ + public partial class BTreeController + { + /// + /// Insert a row/record/cell. + /// + /// the root of the B+ tree. + /// primary key in table tree and indexed column in index tree. + /// new row of values to insert. + /// new root node of the B+ tree + public BTreeNode InsertCell(BTreeNode root, DBRecord key, DBRecord dBRecord) + { + // create a new tree + if (root == null) + { + BTreeNode newRootFromNull = GetNewNode(PageTypes.LeafTablePage); + LeafTableCell newCell = new LeafTableCell(key, dBRecord); + newRootFromNull.InsertBTreeCell(newCell); + return newRootFromNull; + } + // no need to split + if (root.NumCells < MaxCell) + { + InsertNonFull(root, key, dBRecord); + return root; + } + + // need to split, and return with a new root + BTreeNode newRoot = GetNewNode(PageTypes.InternalTablePage); + root.ParentPage = (uint)newRoot.RawPage.PageNumber; + SplitNode(root, newRoot, key); + InsertNonFull(newRoot, key, dBRecord); + return newRoot; + } + + /// + /// Split `nodeTobeSplit`, which has a `parantNode`. + /// + /// node to be split. + /// parent node of `nodeTobeSplit`. + /// the value of new key. This could affect where to split. + private void SplitNode(BTreeNode nodeTobeSplit, BTreeNode parantNode, DBRecord newKey) + { + int i; + // new node will be appended to `nodeTobeSplit` + BTreeNode splitNode = GetNewNode(nodeTobeSplit.PageType); + // tmp is used for the change of parentPage + InternalTableCell tmpCell; + MemoryPage tmpPage; + + // key should be the primary key to be inserted in the parent node + int deleteIndex = nodeTobeSplit.NumCells / 2; + // right bound of the left node + DBRecord rightmostKeyInLeftNode = nodeTobeSplit[deleteIndex - 1].Key; + if ((newKey.GetValues()[0]>= rightmostKeyInLeftNode.GetValues()[0]).BooleanValue) + { + // the new key should be put at the split node on the right + deleteIndex++; + rightmostKeyInLeftNode = nodeTobeSplit[deleteIndex - 1].Key; + } + // `deleteIndex` is now pointing to the first cell of the pending right node + + // loop through the right part of `nodeTobeSplit` + for (i = deleteIndex; i < this.MaxCell; i++) + { + ushort deleteOffSet = nodeTobeSplit.CellOffsetArray[deleteIndex]; + // change the parent Page fields of their children + if (nodeTobeSplit.PageType == PageTypes.InternalTablePage) + { + tmpCell = (InternalTableCell)nodeTobeSplit.GetBTreeCell(deleteOffSet); + tmpPage = _pager.ReadPage((int)tmpCell.ChildPage); + new BTreeNode(tmpPage) + { + ParentPage = (uint)splitNode.RawPage.PageNumber + }; + } + // move the cells in `nodeTobeSplit` belonging to the pending right node to `splitNode` + splitNode.InsertBTreeCell(nodeTobeSplit.GetBTreeCell(deleteOffSet)); + nodeTobeSplit.DeleteBTreeCell(deleteOffSet); + } + // new cell to be inserted to the parent node of `nodeTobeSplit` + // If the `parentNode` need to spilt, this will be wrong. However, it could be ensured not happenning because it is a top-down process. + InternalTableCell newCellToAscend = new InternalTableCell(rightmostKeyInLeftNode, (uint)nodeTobeSplit.RawPage.PageNumber); + + // make alias for readability + BTreeNode leftNode = nodeTobeSplit; + BTreeNode rightNode = splitNode; + // connect two nodes `leftNode` and `rightNode` by `RightPage` pointer + rightNode.RightPage = leftNode.RightPage; + if (leftNode.PageType == PageTypes.LeafTablePage) + { + leftNode.RightPage = (uint)rightNode.RawPage.PageNumber; + } + // if `leftNode` is an internal node, the middle cell in the original `nodeTobeSplit` (the rightmost cell in the now `leftNode`) has to be deleted + else if (leftNode.PageType == PageTypes.InternalTablePage) + { + // for internal node, the `ParentPage` of child page need to be changed + // the rightmost child of `leftNode` sets its parent to `rightNode` + tmpPage = _pager.ReadPage((int)leftNode.RightPage); + new BTreeNode(tmpPage) + { + ParentPage = (uint)rightNode.RawPage.PageNumber + }; + + // the rightmost Cell In the pending Left Node + InternalTableCell rightmostCellInLeftNode = (InternalTableCell)leftNode[deleteIndex - 1]; + // set the rightmost child of `leftNode` to the left child of `rightmostCellInLeftNode` + leftNode.RightPage = rightmostCellInLeftNode.ChildPage; + // leftNode.DeleteBTreeCell(rightmostCellInLeftNode); // the same as the code below, but the code below runs faster + leftNode.DeleteBTreeCell(leftNode.CellOffsetArray[deleteIndex - 1]); + + // the deleted rightmost cell in left node sets the parent of its left child to that left node + tmpPage = _pager.ReadPage((int)rightmostCellInLeftNode.ChildPage); + new BTreeNode(tmpPage) + { + ParentPage = (uint)leftNode.RawPage.PageNumber + }; + } + + rightNode.ParentPage = (uint)parantNode.RawPage.PageNumber; + + // reconnect the particular cell (or right) in the parent node because of the change of the child node + // This is a new empty root + if (parantNode.NumCells == 0) + { + parantNode.RightPage = (uint)rightNode.RawPage.PageNumber; + } + // There are some cell in the parents node + else + { + BTreeCell cell; + (cell, _, _) = parantNode.FindBTreeCell(rightmostKeyInLeftNode); + // The case when the node to be inserted into parent node is in the rightest position + if (cell == null) + { + parantNode.RightPage = (uint)rightNode.RawPage.PageNumber; + } + // The normal case + else + { + InternalTableCell tmp_cell = new InternalTableCell(cell.Key, (uint)rightNode.RawPage.PageNumber); + parantNode.DeleteBTreeCell(cell); + parantNode.InsertBTreeCell(tmp_cell); + } + } + // This must be done after we reconnect the treeNode + parantNode.InsertBTreeCell(newCellToAscend); + } + + /// + /// Insert cell into a non-full node `node` if `node` is a leaf node. + /// If `node` is not the leaf node, the child node of `node` might need to split before recursively performing this function to the child node. + /// `node` should be ensured to be not full. + /// + /// node being inserted + /// new key value + /// new row/record + /// new root node + private BTreeNode InsertNonFull(BTreeNode node, DBRecord newKey, DBRecord dBRecord) + { + // the actual insertion performs in leaf node + if (node.PageType == PageTypes.LeafTablePage) + { + BTreeCell check_repeat; + (check_repeat, _, _) = node.FindBTreeCell(newKey, false); + if (check_repeat != null) + { + throw new RepeatedKeyException($"The primary key to be inserted ({newKey.GetValues()[0]}) is repeated!"); + } + LeafTableCell newCell = new LeafTableCell(newKey, dBRecord); + node.InsertBTreeCell(newCell); + return node; + } + + // find the child node to try to insert + BTreeNode child; + BTreeCell cell; + UInt16 offset; + (cell, offset, _) = node.FindBTreeCell(newKey); + MemoryPage nextpage; + if (offset == 0) // rightest page + { + nextpage = _pager.ReadPage((int)node.RightPage); + child = new BTreeNode(nextpage); + } + else + { + InternalTableCell internalTableCell = (InternalTableCell)cell; + nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); + child = new BTreeNode(nextpage); + } + // child needs to split + if (child.NumCells>= MaxCell) + { + SplitNode(child, node, newKey); + return InsertNonFull(node, newKey, dBRecord); + } + return InsertNonFull(child, newKey, dBRecord); + } + } +} diff --git a/src/MiniSQL.IndexManager/Controllers/BTreeController.cs b/src/MiniSQL.IndexManager/Controllers/BTreeController.cs index b45c74c..164720c 100644 --- a/src/MiniSQL.IndexManager/Controllers/BTreeController.cs +++ b/src/MiniSQL.IndexManager/Controllers/BTreeController.cs @@ -1,16 +1,12 @@ using System; -using System.Collections.Generic; -using System.Runtime; using MiniSQL.BufferManager.Controllers; using MiniSQL.IndexManager.Models; using MiniSQL.BufferManager.Models; using MiniSQL.IndexManager.Interfaces; -using MiniSQL.Library.Models; -using MiniSQL.IndexManager.Utilities; namespace MiniSQL.IndexManager.Controllers { - public class BTreeController : IIndexManager + public partial class BTreeController : IIndexManager { private readonly Pager _pager; private readonly FreeList _freeList; @@ -22,54 +18,14 @@ public BTreeController(Pager pager, FreeList freeList, int maxCell = 4) this._pager = pager; this._freeList = freeList; if (maxCell < 4) - throw new Exception($"maxCell expected at least 4, actual {maxCell}"); + throw new Exception($"maxCell expected at least 4, actually {maxCell}"); this.MaxCell = maxCell; } - // TODO: test - public BTreeNode OccupyNewTableNode() - { - BTreeNode newNode = GetNewNode(PageTypes.LeafTablePage); - return newNode; - } - - // TODO: test - public void RemoveTree(BTreeNode root) - { - if (root.PageType == PageTypes.LeafIndexPage || root.PageType == PageTypes.LeafTablePage) - { - DeleteNode(root); - return; - } - if (root.PageType == PageTypes.InternalIndexPage) - { - foreach (BTreeCell cell in root) - { - MemoryPage page = _pager.ReadPage((int)((InternalIndexCell)cell).ChildPage); - BTreeNode node = new BTreeNode(page); - RemoveTree(node); - } - } - else // (root.PageType == PageTypes.InternalTablePage) - { - foreach (BTreeCell cell in root) - { - MemoryPage page = _pager.ReadPage((int)((InternalTableCell)cell).ChildPage); - BTreeNode node = new BTreeNode(page); - RemoveTree(node); - } - } - MemoryPage rightPage = _pager.ReadPage((int)root.RightPage); - BTreeNode rightNode = new BTreeNode(rightPage); - RemoveTree(rightNode); - // post-order traversal - DeleteNode(root); - } - // recycle page to free list private void DeleteNode(BTreeNode node) { - MemoryPage page = node.GetRawPage(); + MemoryPage page = node.RawPage; node.IsDisabled = true; _freeList.RecyclePage(page); } @@ -89,781 +45,5 @@ private BTreeNode GetNewNode(PageTypes nodeType) return node; } - - - public BTreeNode InsertCell(BTreeNode Root, DBRecord key, DBRecord dBRecord) - { - //create a new root - if (Root == null) - { - BTreeNode root = GetNewNode(PageTypes.LeafTablePage); - LeafTableCell NewCell = new LeafTableCell(key, dBRecord); - root.InsertBTreeCell(NewCell); - return root; - } - //no need to split - if (Root.NumCells < MaxCell) - { - InsertNonFull(Root, key, dBRecord); - return Root; - } - - //need to split,and return with a new root - BTreeNode newRoot = GetNewNode(PageTypes.InternalTablePage); - Root.ParentPage = (uint)newRoot.GetRawPage().PageNumber; - SplitChild(Root, newRoot, key); - InsertNonFull(newRoot, key, dBRecord); - return newRoot; - } - - private void SplitChild(BTreeNode nodeTobeSplit, BTreeNode parantNode, DBRecord newKey) - { - int i; - BTreeNode splitNode = GetNewNode(nodeTobeSplit.PageType); - //tmp is used for the change of parentPage - InternalTableCell tmpCell; - MemoryPage tmpPage; - BTreeNode tmpNode; - - //key should be the primary key to be inserted in the parent node - int DeleteIndex = nodeTobeSplit.NumCells / 2; - DBRecord key = nodeTobeSplit.GetBTreeCell(nodeTobeSplit.CellOffsetArray[DeleteIndex - 1]).Key; - if ((newKey.GetValues()[0]>= key.GetValues()[0]).BooleanValue) - { - DeleteIndex += 1; - key = nodeTobeSplit.GetBTreeCell(nodeTobeSplit.CellOffsetArray[DeleteIndex - 1]).Key; - } - - for (i = DeleteIndex; i < MaxCell; i++) - { - ushort DeleteOffSet = nodeTobeSplit.CellOffsetArray[DeleteIndex]; - //change the parent Page - if (nodeTobeSplit.PageType == PageTypes.InternalTablePage) - { - tmpCell = (InternalTableCell)nodeTobeSplit.GetBTreeCell(DeleteOffSet); - tmpPage = _pager.ReadPage((int)tmpCell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)splitNode.GetRawPage().PageNumber; - } - - splitNode.InsertBTreeCell(nodeTobeSplit.GetBTreeCell(DeleteOffSet)); - nodeTobeSplit.DeleteBTreeCell(DeleteOffSet); - - } - //If the parentNode need to spilt,this will be wrong - InternalTableCell newCell = new InternalTableCell(key, (uint)nodeTobeSplit.GetRawPage().PageNumber); - - //connnect two child node by rightpage - splitNode.RightPage = nodeTobeSplit.RightPage; - if (nodeTobeSplit.PageType == PageTypes.LeafTablePage) - { - nodeTobeSplit.RightPage = (uint)splitNode.GetRawPage().PageNumber; - } - //for a internal node,a cell in nodeTobeSplit has to be deleted - else if (nodeTobeSplit.PageType == PageTypes.InternalTablePage) - { - //for internal node,the parent Page of child page need to be changed - tmpPage = _pager.ReadPage((int)nodeTobeSplit.RightPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)splitNode.GetRawPage().PageNumber; - - - InternalTableCell tmp_cell = (InternalTableCell)nodeTobeSplit.GetBTreeCell(nodeTobeSplit.CellOffsetArray[DeleteIndex - 1]); - nodeTobeSplit.RightPage = tmp_cell.ChildPage; - nodeTobeSplit.DeleteBTreeCell(nodeTobeSplit.CellOffsetArray[DeleteIndex - 1]); - - tmpPage = _pager.ReadPage((int)tmp_cell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)nodeTobeSplit.GetRawPage().PageNumber; - } - - splitNode.ParentPage = (uint)parantNode.GetRawPage().PageNumber; - - //reconnect the particular cell(or right) in the parent node because of the change of the child node - //This is a new empty root - if (parantNode.NumCells == 0) - { - parantNode.RightPage = (uint)splitNode.GetRawPage().PageNumber; - } - //There are some cell in the parents node - else - { - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - (cell, offset, indexInOffsetArray) = parantNode.FindBTreeCell(key); - //The case when the node to be inserted into parent node is in the rightest position - if (cell == null) - { - parantNode.RightPage = (uint)splitNode.GetRawPage().PageNumber; - } - //The normal case - else - { - InternalTableCell tmp_cell = new InternalTableCell(cell.Key, (uint)splitNode.GetRawPage().PageNumber); - parantNode.DeleteBTreeCell(cell); - parantNode.InsertBTreeCell(tmp_cell); - } - } - //This must be done after we reconnect the treeNode - parantNode.InsertBTreeCell(newCell); - - } - - private BTreeNode InsertNonFull(BTreeNode node, DBRecord newKey, DBRecord dBRecord) - { - if (node.PageType == PageTypes.LeafTablePage) - { - BTreeCell check_repeat; - ushort offSet; - int indexinOffsetArray; - (check_repeat,offSet,indexinOffsetArray)=node.FindBTreeCell(newKey,false); - if(check_repeat!=null) - { - - throw new RepeatedKeyException("The primary key to be inserted is repeated!"); - - } - LeafTableCell newCell = new LeafTableCell(newKey, dBRecord); - node.InsertBTreeCell(newCell); - return node; - } - - BTreeNode child; - MemoryPage Nextpage = null; - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - (cell, offset, indexInOffsetArray) = node.FindBTreeCell(newKey); - if (offset == 0) //rightpage - { - Nextpage = _pager.ReadPage((int)node.RightPage); - child = new BTreeNode(Nextpage); - } - else - { - InternalTableCell internalTableCell = (InternalTableCell)cell; - Nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); - child = new BTreeNode(Nextpage); - } - if (child.NumCells>= MaxCell) - { - SplitChild(child, node, newKey); - return InsertNonFull(node, newKey, dBRecord); - - } - return InsertNonFull(child, newKey, dBRecord); - - } - - public BTreeCell FindCell(DBRecord key, BTreeNode root) - { - return InternalFind(key, root); - } - - private BTreeCell InternalFind(DBRecord key, BTreeNode root) - { - BTreeNode child; - MemoryPage Nextpage = null; - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - - if (root.PageType == PageTypes.LeafTablePage) - { - (cell, offset, indexInOffsetArray) = root.FindBTreeCell(key, false); - return cell; - } - - //If it's internal node - (cell, offset, indexInOffsetArray) = root.FindBTreeCell(key); - if (offset == 0) //rightpage - { - Nextpage = _pager.ReadPage((int)root.RightPage); - child = new BTreeNode(Nextpage); - } - else - { - InternalTableCell internalTableCell = (InternalTableCell)cell; - Nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); - child = new BTreeNode(Nextpage); - } - return InternalFind(key, child); - } - - public BTreeNode Delete(DBRecord key, BTreeNode Root) - { - BTreeNode NodeTobeDeleted = FindNode(key, Root); - if (NodeTobeDeleted == null) - { - throw new KeyNotExistException("Cannot find the key!"); - } - return Delete_entry(NodeTobeDeleted, key, Root); - - } - - public BTreeNode Delete(BTreeCell keyCell, BTreeNode Root) - { - DBRecord key = keyCell.Key; - return Delete(key, Root); - } - - private BTreeNode FindNode(DBRecord key, BTreeNode root, bool isFuzzySearch = false) - { - BTreeNode child; - MemoryPage Nextpage = null; - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - - if (root.PageType == PageTypes.LeafTablePage) - { - (cell, offset, indexInOffsetArray) = root.FindBTreeCell(key, isFuzzySearch); - if (cell != null) - return root; - else - return null; - } - - //If it's internal node - (cell, offset, indexInOffsetArray) = root.FindBTreeCell(key); - if (offset == 0) //rightpage - { - Nextpage = _pager.ReadPage((int)root.RightPage); - child = new BTreeNode(Nextpage); - } - else - { - InternalTableCell internalTableCell = (InternalTableCell)cell; - Nextpage = _pager.ReadPage((int)internalTableCell.ChildPage); - child = new BTreeNode(Nextpage); - } - return FindNode(key, child); - } - - private BTreeNode Delete_leaf_redistri(BTreeNode NodetobeDeleted, DBRecord key, BTreeNode Root) - { - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - - MemoryPage parentPage = _pager.ReadPage((int)NodetobeDeleted.ParentPage); - BTreeNode parentNode = new BTreeNode(parentPage); - - (cell, offset, indexInOffsetArray) = parentNode.FindBTreeCell(key); - //the deleted node is not on the right page of parentNode - if (cell != null) - { - MemoryPage brotherPage = _pager.ReadPage((int)NodetobeDeleted.RightPage); - BTreeNode brotherNode = new BTreeNode(brotherPage); - //If there is a node on the left of the deleted node,it need to be connected to the brother node. - if (indexInOffsetArray>= 1) - { - InternalTableCell leftNodeCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[indexInOffsetArray - 1]); - MemoryPage leftPage = _pager.ReadPage((int)leftNodeCell.ChildPage); - BTreeNode leftNode = new BTreeNode(leftPage); - leftNode.RightPage = (uint)brotherNode.GetRawPage().PageNumber; - } - - if (brotherNode.NumCells + NodetobeDeleted.NumCells <= MaxCell) //merge - { - //After the merge,one cell in the parentNode will be deleted - parentNode.DeleteBTreeCell(cell); - //merge two node - for (int i = 0; i < NodetobeDeleted.NumCells; i++) - { - brotherNode.InsertBTreeCell(NodetobeDeleted.GetBTreeCell(NodetobeDeleted.CellOffsetArray[i])); - } - DeleteNode(NodetobeDeleted); - - } - else //redistribute - { - BTreeCell movedCell = brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[0]); - DBRecord newKey = brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[1]).Key; - - NodetobeDeleted.InsertBTreeCell(movedCell); - brotherNode.DeleteBTreeCell(movedCell); - - BTreeCell parent_Cell; - UInt16 parent_offset; - int parent_indexInOffsetArray; - (parent_Cell, parent_offset, parent_indexInOffsetArray) = parentNode.FindBTreeCell(key); - - InternalTableCell newCell = new InternalTableCell(newKey, (uint)NodetobeDeleted.GetRawPage().PageNumber); - parentNode.DeleteBTreeCell(parent_Cell); - parentNode.InsertBTreeCell(newCell); - - } - } - //The node to be deleted is on the rightpage,the brother node is on the left - else - { - InternalTableCell brotherCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1]); - MemoryPage brotherPage = _pager.ReadPage((int)brotherCell.ChildPage); - BTreeNode brotherNode = new BTreeNode(brotherPage); - - //The right page of brother node should be 0 - - brotherNode.RightPage = NodetobeDeleted.RightPage; - - if (brotherNode.NumCells + NodetobeDeleted.NumCells <= MaxCell) //merge - { - //After the merge,one cell in the parentNode will be deleted - parentNode.DeleteBTreeCell(brotherCell); - //merge two node - for (int i = 0; i < NodetobeDeleted.NumCells; i++) - { - brotherNode.InsertBTreeCell(NodetobeDeleted.GetBTreeCell(NodetobeDeleted.CellOffsetArray[i])); - } - DeleteNode(NodetobeDeleted); - parentNode.RightPage = (uint)brotherNode.GetRawPage().PageNumber; - - } - else //redistribute - { - BTreeCell movedCell = brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[brotherNode.NumCells - 1]); - DBRecord newKey = movedCell.Key; - - NodetobeDeleted.InsertBTreeCell(movedCell); - brotherNode.DeleteBTreeCell(movedCell); - - BTreeCell parent_Cell; - UInt16 parent_offset; - int parent_indexInOffsetArray; - (parent_Cell, parent_offset, parent_indexInOffsetArray) = parentNode.FindBTreeCell(key); - - InternalTableCell newCell = new InternalTableCell(newKey, (uint)NodetobeDeleted.GetRawPage().PageNumber); - parentNode.DeleteBTreeCell(parent_Cell); - parentNode.InsertBTreeCell(newCell); - - } - - } - - - NodetobeDeleted = parentNode; - //deal with parent Nodes - return Delete_internal_redistri(NodetobeDeleted, key, Root); - } - - private BTreeNode Delete_internal_redistri(BTreeNode NodetobeDeleted, DBRecord key, BTreeNode Root) - { - InternalTableCell tmpCell; - MemoryPage tmpPage; - BTreeNode tmpNode; - - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - - MemoryPage parentPage = null; - BTreeNode parentNode = null; - - while (NodetobeDeleted.NumCells < (MaxCell + 1) / 2) - { - //The root - if (NodetobeDeleted.ParentPage == 0) - { - if (NodetobeDeleted.NumCells == 0) - { - MemoryPage NewRootPage = _pager.ReadPage((int)NodetobeDeleted.RightPage); - BTreeNode newRoot = new BTreeNode(NewRootPage); - newRoot.ParentPage = 0; - return newRoot; - } - return Root; - } - else - { - parentPage = _pager.ReadPage((int)NodetobeDeleted.ParentPage); - parentNode = new BTreeNode(parentPage); - (cell, offset, indexInOffsetArray) = parentNode.FindBTreeCell(key); - //The node to be deleted isn't on the rightpage - if (cell != null) - { - InternalTableCell brotherCell = null; - MemoryPage brotherPage = null; - BTreeNode brotherNode = null; - //if the right brother is on rightpage - if (indexInOffsetArray + 1 == parentNode.NumCells) - { - brotherPage = _pager.ReadPage((int)parentNode.RightPage); - brotherNode = new BTreeNode(brotherPage); - - } - else - { - brotherCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[indexInOffsetArray + 1]); - brotherPage = _pager.ReadPage((int)brotherCell.ChildPage); - brotherNode = new BTreeNode(brotherPage); - } - //merge - if (brotherNode.NumCells + NodetobeDeleted.NumCells < MaxCell) - { - for (int i = 0; i < NodetobeDeleted.NumCells; i++) - { - tmpCell = (InternalTableCell)NodetobeDeleted.GetBTreeCell(NodetobeDeleted.CellOffsetArray[i]); - - brotherNode.InsertBTreeCell(tmpCell); - - tmpPage = _pager.ReadPage((int)tmpCell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)brotherNode.GetRawPage().PageNumber; - } - //move the cell in parentNode to brotherNode - InternalTableCell insertCell = new InternalTableCell(cell.Key, (uint)NodetobeDeleted.RightPage); - brotherNode.InsertBTreeCell(insertCell); - tmpPage = _pager.ReadPage((int)insertCell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)brotherNode.GetRawPage().PageNumber; - - DeleteNode(NodetobeDeleted); - parentNode.DeleteBTreeCell(cell); - } - //redistribute - else - { - InternalTableCell movedCell = (InternalTableCell)brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[0]); - DBRecord upperKey = movedCell.Key; - DBRecord downKey = cell.Key; - - InternalTableCell insertDeletedCell = new InternalTableCell(downKey, (uint)NodetobeDeleted.RightPage); - NodetobeDeleted.InsertBTreeCell(insertDeletedCell); - NodetobeDeleted.RightPage = movedCell.ChildPage; - - tmpPage = _pager.ReadPage((int)movedCell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)NodetobeDeleted.GetRawPage().PageNumber; - - InternalTableCell insertParentCell = new InternalTableCell(upperKey, (uint)NodetobeDeleted.GetRawPage().PageNumber); - parentNode.DeleteBTreeCell(cell); - parentNode.InsertBTreeCell(insertParentCell); - brotherNode.DeleteBTreeCell(movedCell); - - } - - } - //The node to be deleted is on the rightpage - else - { - InternalTableCell brotherCell = null; - MemoryPage brotherPage = null; - BTreeNode brotherNode = null; - - brotherCell = (InternalTableCell)parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1]); - brotherPage = _pager.ReadPage((int)brotherCell.ChildPage); - brotherNode = new BTreeNode(brotherPage); - //merge - if (brotherNode.NumCells + NodetobeDeleted.NumCells < MaxCell) - { - for (int i = 0; i < brotherNode.NumCells; i++) - { - tmpCell = (InternalTableCell)brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[i]); - - NodetobeDeleted.InsertBTreeCell(tmpCell); - - tmpPage = _pager.ReadPage((int)tmpCell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)NodetobeDeleted.GetRawPage().PageNumber; - } - //move the cell in parentNode to brotherNode - InternalTableCell insertCell = new InternalTableCell(brotherCell.Key, (uint)brotherNode.RightPage); - NodetobeDeleted.InsertBTreeCell(insertCell); - tmpPage = _pager.ReadPage((int)insertCell.ChildPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)NodetobeDeleted.GetRawPage().PageNumber; - - DeleteNode(brotherNode); - parentNode.DeleteBTreeCell(parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1])); - } - //redistribute - else - { - DBRecord downKey = parentNode.GetBTreeCell(parentNode.CellOffsetArray[parentNode.NumCells - 1]).Key; - InternalTableCell insertDeletedCell = new InternalTableCell(downKey, brotherNode.RightPage); - NodetobeDeleted.InsertBTreeCell(insertDeletedCell); - - - InternalTableCell movedCell = (InternalTableCell)brotherNode.GetBTreeCell(brotherNode.CellOffsetArray[brotherNode.NumCells - 1]); - brotherNode.RightPage = movedCell.ChildPage; - DBRecord upperKey = movedCell.Key; - InternalTableCell insertParentCell = new InternalTableCell(upperKey, (uint)brotherNode.GetRawPage().PageNumber); - parentNode.InsertBTreeCell(insertParentCell); - brotherNode.DeleteBTreeCell(movedCell); - - tmpPage = _pager.ReadPage((int)brotherNode.RightPage); - tmpNode = new BTreeNode(tmpPage); - tmpNode.ParentPage = (uint)brotherNode.GetRawPage().PageNumber; - } - } - } - NodetobeDeleted = parentNode; - } - return Root; - } - - private BTreeNode Delete_entry(BTreeNode NodetobeDeleted, DBRecord key, BTreeNode Root) - { - BTreeCell cell; - UInt16 offset; - int indexInOffsetArray; - (cell, offset, indexInOffsetArray) = NodetobeDeleted.FindBTreeCell(key, false); - NodetobeDeleted.DeleteBTreeCell(cell); - - if (NodetobeDeleted.NumCells < MaxCell / 2 && NodetobeDeleted.ParentPage != 0) - { - return Delete_leaf_redistri(NodetobeDeleted, key, Root); - } - return Root; - } - - private BTreeNode FindMin(BTreeNode root) - { - BTreeNode child; - MemoryPage Nextpage = null; - InternalTableCell childCell; - - if (root.PageType == PageTypes.LeafTablePage) - { - return root; - } - childCell = (InternalTableCell)root.GetBTreeCell(root.CellOffsetArray[0]); - Nextpage = _pager.ReadPage((int)childCell.ChildPage); - child = new BTreeNode(Nextpage); - - return FindMin(child); - } - - private List LessFind(BTreeNode begin, Expression expression, List attributeDeclarations, AtomValue UpperBound, bool isEqual) - { - MemoryPage Nextpage = null; - List result = new List(); - LeafTableCell leafCell; - - while (true) - { - foreach (var cell in begin) - { - if (((cell.Key.GetValues()[0]> UpperBound).BooleanValue && isEqual) || - ((cell.Key.GetValues()[0]>= UpperBound).BooleanValue) && !isEqual) - { - return result; - } - leafCell = (LeafTableCell)cell; - - if (expression.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) - { - result.Add(cell); - } - } - if (begin.RightPage == 0) - { - return result; - } - Nextpage = _pager.ReadPage((int)begin.RightPage); - begin = new BTreeNode(Nextpage); - } - } - - private List MoreFind(BTreeNode begin_Node, int begin_Index, Expression expression, List attributeDeclarations, bool isEqual) - { - MemoryPage Nextpage = null; - List result = new List(); - LeafTableCell leafCell; - - if (isEqual) - { - leafCell = (LeafTableCell)begin_Node.GetBTreeCell(begin_Node.CellOffsetArray[begin_Index]); - if (expression.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) - { - result.Add(leafCell); - } - - } - for (int i = begin_Index + 1; i < begin_Node.NumCells; i++) - { - leafCell = (LeafTableCell)begin_Node.GetBTreeCell(begin_Node.CellOffsetArray[i]); - if (expression.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) - { - result.Add(leafCell); - } - } - while (begin_Node.RightPage != 0) - { - Nextpage = _pager.ReadPage((int)begin_Node.RightPage); - begin_Node = new BTreeNode(Nextpage); - - foreach (var cell in begin_Node) - { - leafCell = (LeafTableCell)cell; - if (expression.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) - { - result.Add(cell); - } - } - - } - return result; - } - - - - - public List FindCells(BTreeNode root, Expression expression, string keyName, List attributeDeclarations) - { - if (expression == null) - { - return LinearSearch(root, expression, attributeDeclarations); - } - else if (expression.Ands.ContainsKey(keyName)) - { - List result = new List(); - List values = new List(); - BTreeNode beginNode; - - BTreeCell cell; - UInt16 offset; - int begin_Index; - - AtomValue bound = expression.Ands[keyName].RightOperant.ConcreteValue; - - values.Add(bound); - DBRecord keyFind = new DBRecord(values); - switch (expression.Ands[keyName].Operator) - { - case Operator.NotEqual: - return LinearSearch(root, expression, attributeDeclarations); - - case Operator.Equal: - LeafTableCell tmpCell = (LeafTableCell)FindCell(keyFind, root); - if (tmpCell == null) - { - break; - } - else if (expression.Calculate(attributeDeclarations, tmpCell.DBRecord.GetValues()).BooleanValue == true) - { - result.Add(tmpCell); - } - break; - - case Operator.LessThan: - beginNode = FindMin(root); - return LessFind(beginNode, expression, attributeDeclarations, bound, false); - case Operator.LessThanOrEqualTo: - beginNode = FindMin(root); - return LessFind(beginNode, expression, attributeDeclarations, bound, true); - case Operator.MoreThan: - beginNode = FindNode(keyFind, root, true); - (cell, offset, begin_Index) = beginNode.FindBTreeCell(keyFind); - //2 possible sitiutions for cell==null: - //1:The keyFind is bigger than all the key - //2:The keyFind is just between the bigest one in this node and the smallest one in next node - if (cell == null) - { - if (beginNode.RightPage == 0) - { - return result; - } - else - { - begin_Index = 0; - MemoryPage Nextpage = _pager.ReadPage((int)beginNode.RightPage); - beginNode = new BTreeNode(Nextpage); - } - } - return MoreFind(beginNode, begin_Index, expression, attributeDeclarations, false); - case Operator.MoreThanOrEqualTo: - beginNode = FindNode(keyFind, root, true); - (cell, offset, begin_Index) = beginNode.FindBTreeCell(keyFind); - if (cell == null) - { - if (beginNode.RightPage == 0) - { - return result; - } - else - { - begin_Index = 0; - MemoryPage Nextpage = _pager.ReadPage((int)beginNode.RightPage); - beginNode = new BTreeNode(Nextpage); - } - } - return MoreFind(beginNode, begin_Index, expression, attributeDeclarations, true); - default: - throw new Exception("The Operant is not supported!"); - } - //This step may not need? - return result; - - } - else - { - return LinearSearch(root, expression, attributeDeclarations); - } - - - } - - private List LinearSearch(BTreeNode root, Expression expression, List attributeDeclarations) - { - BTreeNode beginNode = FindMin(root); - - MemoryPage Nextpage = null; - List result = new List(); - LeafTableCell leafCell; - - while (true) - { - foreach (var cell in beginNode) - { - leafCell = (LeafTableCell)cell; - if (expression == null) - { - result.Add(cell); - } - else if (expression.Calculate(attributeDeclarations, leafCell.DBRecord.GetValues()).BooleanValue == true) - { - result.Add(cell); - } - } - if (beginNode.RightPage == 0) - { - return result; - } - Nextpage = _pager.ReadPage((int)beginNode.RightPage); - beginNode = new BTreeNode(Nextpage); - } - } - - public System.Collections.Generic.IEnumerable LinearSearch(BTreeNode root) - { - BTreeNode beginNode = FindMin(root); - List result = new List(); - - while (true) - { - foreach (var cell in beginNode) - { - yield return cell; - } - if (beginNode.RightPage == 0) - { - break; - } - beginNode = BTreeNodeHelper.GetBTreeNode(_pager, (int)beginNode.RightPage); - } - } - - public BTreeNode DeleteCells(BTreeNode root, Expression expression, string keyName, List attributeDeclarations) - { - List nodesTobeDeleted = FindCells(root, expression, keyName, attributeDeclarations); - foreach (var cell in nodesTobeDeleted) - { - root = Delete(cell, root); - } - return root; - } - } } diff --git a/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs b/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs index 70ec517..daf4a46 100644 --- a/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs +++ b/src/MiniSQL.IndexManager/Interfaces/IIndexManager.cs @@ -1,35 +1,59 @@ using MiniSQL.Library.Models; using MiniSQL.IndexManager.Models; using System.Collections.Generic; -using System; namespace MiniSQL.IndexManager.Interfaces { - public class KeyNotExistException : Exception - { - public KeyNotExistException() { } - public KeyNotExistException(string message) : base(message) { } - } - - public class RepeatedKeyException : Exception - { - public RepeatedKeyException() { } - public RepeatedKeyException(string message) : base(message) { } - } - public interface IIndexManager { - // when create table + /// + /// Use when creating table + /// + /// The root node of the new B+ tree BTreeNode OccupyNewTableNode(); - // when drop table + /// + /// Use when dropping table + /// + /// root node of the B+ Tree void RemoveTree(BTreeNode root); - // insert cell - BTreeNode InsertCell(BTreeNode Root, DBRecord key, DBRecord dBRecord); - // delete cell(s) that satisfy `expression` - BTreeNode DeleteCells(BTreeNode root, Expression expression, string keyName, List attributeDeclarations); - // return matches that satisfy `expression` - List FindCells(BTreeNode root, Expression expression, string keyName, List attributeDeclarations); + /// + /// Insert a row/record/cell + /// + /// the root of the B+ tree + /// primary key in table tree and indexed column in index tree + /// new row of values to insert + /// new root node of the B+ tree + BTreeNode InsertCell(BTreeNode root, DBRecord key, DBRecord dBRecord); + /// + /// Delete cell(s) that satisfy `conDition` + /// + /// the root of the B+ tree + /// condition to satisfy + /// primary key in table tree; indexed value in index tree + /// the names of the columns + /// new root node of the B+ tree + BTreeNode DeleteCells(BTreeNode root, Expression condition, string keyName, List attributeDeclarations); + /// + /// Return matches that satisfy `condition` + /// + /// the root of the B+ tree + /// condition to satisfy + /// primary key in table tree; indexed value in index tree + /// the names of the columns + /// matches that satisfy `condition` + List FindCells(BTreeNode root, Expression condition, string keyName, List attributeDeclarations); + /// + /// Find a row/record/cell by the key value + /// + /// primary key in table tree; indexed value in index tree + /// the root of the B+ tree + /// the matched cell BTreeCell FindCell(DBRecord key, BTreeNode root); - System.Collections.Generic.IEnumerable LinearSearch(BTreeNode root); + /// + /// Enumerate all leaf nodes of the B+ tree + /// + /// the root of the B+ tree + /// each leaf node + IEnumerable LinearSearch(BTreeNode root); } } diff --git a/src/MiniSQL.IndexManager/MiniSQL.IndexManager.csproj b/src/MiniSQL.IndexManager/MiniSQL.IndexManager.csproj index ea6c2b7..9a8d08d 100644 --- a/src/MiniSQL.IndexManager/MiniSQL.IndexManager.csproj +++ b/src/MiniSQL.IndexManager/MiniSQL.IndexManager.csproj @@ -6,8 +6,9 @@ - Exe - netcoreapp3.1 + true + + net5.0 diff --git a/src/MiniSQL.IndexManager/Models/B-Tree/BTreeNode.cs b/src/MiniSQL.IndexManager/Models/B-Tree/BTreeNode.cs index dfec4e6..1cf253c 100644 --- a/src/MiniSQL.IndexManager/Models/B-Tree/BTreeNode.cs +++ b/src/MiniSQL.IndexManager/Models/B-Tree/BTreeNode.cs @@ -6,7 +6,6 @@ namespace MiniSQL.IndexManager.Models { - // TODO: to test the inter-node operations // The term "offset" is the same as "address" // each node exclusively owns one page // <0 (1 byte)> @@ -18,9 +17,12 @@ public PageTypes PageType get { return (PageTypes)_page.Data[0 + _page.AvaliableOffset]; } private set { _page.Data[0 + _page.AvaliableOffset] = (byte)value; } } - // The byte offset at which the free space starts. - // Note that this must be updated every time the cell offset array grows. - public UInt16 FreeOffset + /// + /// The byte offset at which the free space starts. + /// Note that this must be updated every time the cell offset array grows. + /// + /// + private UInt16 FreeOffset { get { return BitConverter.ToUInt16(_page.Data, 1 + _page.AvaliableOffset); } set { Array.Copy(BitConverter.GetBytes(value), 0, _page.Data, 1 + _page.AvaliableOffset, 2); } @@ -29,19 +31,25 @@ public UInt16 FreeOffset public UInt16 NumCells { get { return BitConverter.ToUInt16(_page.Data, 3 + _page.AvaliableOffset); } - set { Array.Copy(BitConverter.GetBytes(value), 0, _page.Data, 3 + _page.AvaliableOffset, 2); } + private set { Array.Copy(BitConverter.GetBytes(value), 0, _page.Data, 3 + _page.AvaliableOffset, 2); } } - // The byte offset at which the cells start. - // If the page contains no cells, this field contains the value PageSize. - // This value must be updated every time a cell is added. - public UInt16 CellsOffset + /// + /// The byte offset at which the cells start. + /// If the page contains no cells, this field contains the value PageSize. + /// This value must be updated every time a cell is added. + /// + /// + private UInt16 CellsOffset { get { return BitConverter.ToUInt16(_page.Data, 5 + _page.AvaliableOffset); } set { Array.Copy(BitConverter.GetBytes(value), 0, _page.Data, 5 + _page.AvaliableOffset, 2); } } - // deprecated: internal node only - // WORKAROUND: all types of node have the `RightPage` pointer - // RightPage pointer is, essentially, the "rightmost pointer" in a B-Tree node + /// + /// deprecated: internal node only + /// WORKAROUND: all types of node have the `RightPage` pointer + /// RightPage pointer is, essentially, the "rightmost pointer" in a B-Tree node + /// + /// public UInt32 RightPage { get { return BitConverter.ToUInt32(_page.Data, 8 + _page.AvaliableOffset); } @@ -54,12 +62,24 @@ public UInt32 ParentPage set { Array.Copy(BitConverter.GetBytes(value), 0, _page.Data, 12 + _page.AvaliableOffset, 4); } } - // if tree node is freed/disabled + /// + /// If tree node is freed/disabled + /// + /// public bool IsDisabled { get; set; } = false; - // the offset array at the low address of the page - // the array indicates the offset (address) of each cell at the high address space - // the order of the array is carefully set in ascending order. It is based on the first value of `Key` of each cell. + /// + /// Alias for the number of cells + /// + /// + public int Count { get => this.NumCells; } + + /// + /// the offset array at the low address of the page + /// the array indicates the offset (address) of each cell at the high address space + /// the order of the array is carefully set in ascending order. It is based on the first value of `Key` of each cell. + /// + /// public List CellOffsetArray { get @@ -68,7 +88,7 @@ public List CellOffsetArray List offsets = new List(); int i; // locates the first item in the offset array - int startAddress = this.FreeOffset - this.NumCells * 2; + int startAddress = this.FreeOffset - (this.NumCells * 2); // visits those items one-by-one and load them to the container for (i = 0; i < this.NumCells; i++) { @@ -82,7 +102,7 @@ public List CellOffsetArray private set { // locates the first item in the offset array - int startAddress = this.FreeOffset - this.NumCells * 2; + int startAddress = this.FreeOffset - (this.NumCells * 2); // visits those items one-by-one and copy them to page foreach (UInt16 offset in value) { @@ -101,17 +121,19 @@ public BTreeNode(MemoryPage assembledPage) this._page = assembledPage; } + // constructor public BTreeNode(MemoryPage emptyPage, PageTypes pageType) { this._page = emptyPage; InitializeEmptyFormat(pageType); } - // use it when freeing this node - public MemoryPage GetRawPage() - { - return _page; - } + /// + /// The memory page behind this node. + /// Use it when freeing this node, but no necessarily. + /// + /// The memory page behind this node + public MemoryPage RawPage { get => _page; } // formatting an empty page with initialized B-Tree node (page) header public void InitializeEmptyFormat(PageTypes pageType) @@ -150,14 +172,20 @@ public void InitializeEmptyFormat(PageTypes pageType) this.NumCells = 0; } - // delete a tree cell + /// + /// Delete a tree cell + /// + /// cell to be removed public void DeleteBTreeCell(BTreeCell cell) { (BTreeCell cellFound, UInt16 offset, int indexInOffsetArray) = FindBTreeCell(cell, false); DeleteBTreeCell(offset); } - // NOTICE: remember to re-get the `CellOffsetArray` after deletion + /// + /// NOTICE: remember to re-get the `CellOffsetArray` after deletion + /// + /// the address/offset of the cell in this node public void DeleteBTreeCell(UInt16 address) { List offsetsSorted = this.CellOffsetArray; @@ -195,32 +223,34 @@ public void DeleteBTreeCell(UInt16 address) this.CellsOffset += (ushort)sizeOfDeletingBTreeCell; } - // get a cell given an offset (address) - // NOTICE: you are only getting a COPY, any modification on the cell will NOT affect the node + /// + /// get a cell given an offset (address) + /// NOTICE: you are only getting a COPY, any modification on the cell will NOT affect the node + /// + /// the address/offset of the cell in this node + /// a COPY of the matched cell public BTreeCell GetBTreeCell(UInt32 address) { BTreeCell cell = null; switch (this.PageType) { case PageTypes.InternalIndexPage: - cell = new InternalIndexCell(_page.Data, (int)address); - break; + return new InternalIndexCell(_page.Data, (int)address); case PageTypes.InternalTablePage: - cell = new InternalTableCell(_page.Data, (int)address); - break; + return new InternalTableCell(_page.Data, (int)address); case PageTypes.LeafIndexPage: - cell = new LeafIndexCell(_page.Data, (int)address); - break; + return new LeafIndexCell(_page.Data, (int)address); case PageTypes.LeafTablePage: - cell = new LeafTableCell(_page.Data, (int)address); - break; + return new LeafTableCell(_page.Data, (int)address); default: throw new Exception($"Page type {this.PageType} does not exist"); } - return cell; } - // insert a cell. It will place the new cell in ascending order + /// + /// Insert a cell. It will place the new cell in ascending order + /// + /// new cell to insert public void InsertBTreeCell(BTreeCell cell) { byte[] raw = cell.Pack(); @@ -249,29 +279,51 @@ public void InsertBTreeCell(BTreeCell cell) this.CellOffsetArray = offsets; } - // NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s - // if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 + /// + /// NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 + /// + /// cell to be found + /// if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// found cells; offset/address in the node, index in the `CellOffsetArray` public (BTreeCell cell, UInt16 offset, int indexInOffsetArray) FindBTreeCell(BTreeCell cell, bool isFuzzySearch = true) { return FindBTreeCell(cell.Key, isFuzzySearch); } - // NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s - // if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 + /// + /// NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 + /// + /// primary key in table tree; indexed value in index tree + /// if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// found cells; offset/address in the node, index in the `CellOffsetArray` public (BTreeCell cell, UInt16 offset, int indexInOffsetArray) FindBTreeCell(DBRecord key, bool isFuzzySearch = true) { List keyValues = key.GetValues(); return FindBTreeCell(keyValues, isFuzzySearch); } - // NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s - // if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 - // WORKAROUND: only the first key is used. The remaining keys will be ignored + /// + /// NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 + /// WORKAROUND: only the first key is used. The remaining keys will be ignored + /// + /// primary keys in table tree; indexed values in index tree + /// if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// found cells; offset/address in the node, index in the `CellOffsetArray` public (BTreeCell cell, UInt16 offset, int indexInOffsetArray) FindBTreeCell(List keys, bool isFuzzySearch = true) { return FindBTreeCell(keys[0], isFuzzySearch); } + /// + /// NOTICE: if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// if no cell matches, the output `cell` field will be `null` and `offset` will be set to 0 + /// + /// primary key in table tree; indexed value in index tree + /// if `isFuzzySearch`, this function will return the first cell that with key equal or larger than that of `cell`'s + /// found cells; offset/address in the node, index in the `CellOffsetArray` public (BTreeCell cell, UInt16 offset, int indexInOffsetArray) FindBTreeCell(AtomValue key, bool isFuzzySearch = true) { // get the list of existing peers to visit @@ -345,18 +397,6 @@ public void InsertBTreeCell(BTreeCell cell) return (peer, offset, i); } - // TODO - // modify field `ChildPage` on internal index cells or internal table cells - public void ChangeChildPage(int indexInOffsetArray, UInt32 newChildPage) - { - if (this.PageType == PageTypes.LeafIndexPage - || this.PageType == PageTypes.LeafTablePage) - { - throw new Exception("Leaf Cells do not have field `ChildPage`"); - } - - } - // make this object to be iterable public IEnumerator GetEnumerator() { @@ -374,6 +414,10 @@ IEnumerator IEnumerable.GetEnumerator() } // overrides "object[index]" operator + /// + /// NOTICE: you are only getting a COPY, any modification on the cell will NOT affect the node + /// + /// public BTreeCell this[int index] { get diff --git a/src/MiniSQL.IndexManager/Models/B-Tree/BTreeTestCases.cs b/src/MiniSQL.IndexManager/Models/B-Tree/BTreeTestCases.cs index 4c6fd17..b858263 100644 --- a/src/MiniSQL.IndexManager/Models/B-Tree/BTreeTestCases.cs +++ b/src/MiniSQL.IndexManager/Models/B-Tree/BTreeTestCases.cs @@ -14,8 +14,8 @@ public static class BTreeTestCases { public static void TestAll() { - // TestLeafTableNode(); - // TestMaxHeightBTree(); + TestLeafTableNode(); + TestMaxHeightBTree(); } static void TestMaxHeightBTree() diff --git a/src/MiniSQL.IndexManager/Models/B-Tree/DBRecord.cs b/src/MiniSQL.IndexManager/Models/B-Tree/DBRecord.cs index 4551801..6e5943a 100644 --- a/src/MiniSQL.IndexManager/Models/B-Tree/DBRecord.cs +++ b/src/MiniSQL.IndexManager/Models/B-Tree/DBRecord.cs @@ -41,7 +41,7 @@ public int RecordSize // the list of the types of each field at the head of the record public List HeaderList { get; private set; } = new List(); // the list of offsets to each field - private List FieldOffsets = new List(); + private readonly List FieldOffsets = new List(); // constructor public DBRecord(byte[] data, int startIndex) @@ -84,8 +84,9 @@ public List GetValues() value.FloatValue = BitConverter.ToDouble(this.FieldData, this.FieldOffsets[i]); } else if (headerValue == (int)HeaderValue.NULL) + { value.Type = AttributeTypes.Null; - + } else if ((headerValue - (int)HeaderValue.TEXT) % 2 == 0) { value.Type = AttributeTypes.Char; @@ -94,7 +95,9 @@ public List GetValues() value.StringValue = Encoding.UTF8.GetString(this.FieldData, this.FieldOffsets[i], stringLength).TrimEnd('0円'); } else + { throw new Exception($"Header value {headerValue} does not exists"); + } values.Add(value); } diff --git a/src/MiniSQL.IndexManager/Program.cs b/src/MiniSQL.IndexManager/Program.cs index 8a974de..230bea0 100644 --- a/src/MiniSQL.IndexManager/Program.cs +++ b/src/MiniSQL.IndexManager/Program.cs @@ -5,8 +5,10 @@ using MiniSQL.BufferManager.Controllers; using MiniSQL.BufferManager.Models; using MiniSQL.IndexManager.Controllers; +using MiniSQL.IndexManager.Interfaces; using MiniSQL.IndexManager.Models; using MiniSQL.IndexManager.Utilities; +using MiniSQL.Library.Exceptions; using MiniSQL.Library.Models; namespace MiniSQL.IndexManager @@ -17,51 +19,48 @@ static void Main(string[] args) { Console.WriteLine("[IndexManager] Test Begin"); - //BTreeTestCases.TestAll(); + // BTreeTestCases.TestAll(); // TestMaxHeightBTree(8, false, true, true); - //BugTest1(); + BugTest1(); - // Bugtest2(); + Bugtest2(); - // TODO: Fix issue at the #6 stage - // BugTest3(); + BugTest3(); - //TestExpressionFind(); + TestExpressionFind(); - //TestExpressionDelete(); + TestExpressionDelete(); - //TestInsertSplit(200); + TestBTreeInsert(); - //TestBTreeInsert(); - - //TestBTreeDelete(); + TestBTreeDelete(); HardTestForBTree(); - // TestDBRecord(); + TestDBRecord(); + + TestLeafTableCell(); - // TestLeafTableCell(); + TestInternalTableCell(); - // TestInternalTableCell(); + TestInternalIndexCell(); - // TestInternalIndexCell(); + TestLeafIndexCell(); - // TestLeafIndexCell(); + TestInsertIntoAndDeletionInsideBTreeNode(); // TestPager(); // TestPagerSwapping(); - //TestInsertIntoAndDeletionInsideBTreeNode(); - // TestFreeList(); Console.WriteLine("[IndexManager] Test End"); } - // TODO: Fix issue at the #6 stage + // Fixed issue at the #6 stage static void BugTest3() { string dbPath = "./testdbfile.minidb"; @@ -103,7 +102,7 @@ record = GetTestBRecord(2); record = GetTestBRecord(4); keyRecord = GetTestBRecord(4); root = controller.InsertCell(root, keyRecord, record); - + BTreeNodeHelper.VisualizeIntegerTree(pager, root); // test 5 // keyRecord = GetTestBRecord(1109110087); @@ -357,6 +356,7 @@ record = GetTestRecord_expression(i, "www", (float)1.3); BTreeNodeHelper.VisualizeIntegerTree(pager, root); + pager.Close(); } static void TestExpressionFind() @@ -415,6 +415,7 @@ record = GetTestRecord_expression(i, "www", (float)1.3); Console.WriteLine(); } + pager.Close(); } private static DBRecord GetTestRecord_expression(int value_1, string value_2, float value_3) @@ -472,13 +473,13 @@ private static Expression GetAndsExpression() // <= Expression node4 = new Expression(); node4.Operator = Operator.LessThanOrEqualTo; - node4.LeftOperant = node8; - node4.RightOperant = node9; + node4.LeftOperand = node8; + node4.RightOperand = node9; // <= Expression node5 = new Expression(); node5.Operator = Operator.LessThanOrEqualTo; - node5.LeftOperant = node10; - node5.RightOperant = node11; + node5.LeftOperand = node10; + node5.RightOperand = node11; // 6.6 Expression node6 = new Expression(); node6.Operator = Operator.AtomConcreteValue; @@ -492,18 +493,18 @@ private static Expression GetAndsExpression() // and Expression node2 = new Expression(); node2.Operator = Operator.And; - node2.LeftOperant = node4; - node2.RightOperant = node5; + node2.LeftOperand = node4; + node2.RightOperand = node5; //> Expression node3 = new Expression(); node3.Operator = Operator.MoreThan; - node3.LeftOperant = node6; - node3.RightOperant = node7; + node3.LeftOperand = node6; + node3.RightOperand = node7; // and Expression node1 = new Expression(); node1.Operator = Operator.And; - node1.LeftOperant = node2; - node1.RightOperant = node3; + node1.LeftOperand = node2; + node1.RightOperand = node3; return node1; } @@ -613,6 +614,7 @@ static void TestBTreeDelete() Debug.Assert(result != null); Debug.Assert(result.Key.GetValues()[0].IntegerValue == 7); + pager.Close(); } static void HardTestForBTree() @@ -621,14 +623,14 @@ static void HardTestForBTree() File.Delete(dbPath); Pager pager = new Pager(dbPath); FreeList freeList = new FreeList(pager); - BTreeController controller = new BTreeController(pager, freeList); + BTreeController controller = new BTreeController(pager, freeList, 4); BTreeNode root = null; LeafTableCell result = null; //Construct BTree for (int i = 1; i < 20; i++) { - DBRecord record = GetTestBRecord(i+100); + DBRecord record = GetTestBRecord(i + 100); DBRecord keyRecord = GetTestBRecord(i); root = controller.InsertCell(root, keyRecord, record); @@ -637,13 +639,31 @@ static void HardTestForBTree() Debug.Assert(result.Key.GetValues()[0].IntegerValue == i); } + // test inserting records with repeated primary keys DBRecord record_D = GetTestBRecord(103); DBRecord keyRecord_D = GetTestBRecord(3); - root = controller.InsertCell(root, keyRecord_D, record_D); - + bool isError = false; + try + { + root = controller.InsertCell(root, keyRecord_D, record_D); + } + catch (RepeatedKeyException) + { + isError = true; + } + Debug.Assert(isError == true); + + isError = false; record_D = GetTestBRecord(105); keyRecord_D = GetTestBRecord(5); - root = controller.InsertCell(root, keyRecord_D, record_D); + try + { + root = controller.InsertCell(root, keyRecord_D, record_D); + } + catch (RepeatedKeyException) + { + isError = true; + } BTreeNodeHelper.VisualizeIntegerTree(pager, root); @@ -715,10 +735,9 @@ static void HardTestForBTree() } + pager.Close(); } - - static void TestBTreeInsert() { LeafTableCell result = null; diff --git a/src/MiniSQL.IndexManager/Utilities/BTreeNodeHelper.cs b/src/MiniSQL.IndexManager/Utilities/BTreeNodeHelper.cs index 1aa316b..b0067a7 100644 --- a/src/MiniSQL.IndexManager/Utilities/BTreeNodeHelper.cs +++ b/src/MiniSQL.IndexManager/Utilities/BTreeNodeHelper.cs @@ -10,9 +10,9 @@ namespace MiniSQL.IndexManager.Utilities { public static class BTreeNodeHelper { - public static BTreeNode GetBTreeNode(Pager pager, int rootPage) + public static BTreeNode GetBTreeNode(Pager pager, int pageNumber) { - MemoryPage page = pager.ReadPage(rootPage); + MemoryPage page = pager.ReadPage(pageNumber); BTreeNode node = new BTreeNode(page); return node; } diff --git a/src/MiniSQL.Interpreter/Parsing.cs b/src/MiniSQL.Interpreter/Controllers/Parsing.cs similarity index 93% rename from src/MiniSQL.Interpreter/Parsing.cs rename to src/MiniSQL.Interpreter/Controllers/Parsing.cs index 2ff5009..6d36fdc 100644 --- a/src/MiniSQL.Interpreter/Parsing.cs +++ b/src/MiniSQL.Interpreter/Controllers/Parsing.cs @@ -5,7 +5,7 @@ using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; -namespace MiniSQL.Interpreter +namespace MiniSQL.Interpreter.Controllers { public class Parsing : IInterpreter { @@ -16,7 +16,7 @@ public Query GetQuery(string input) public static Query StaticGetQuery(string input) { - ICharStream stream = CharStreams.fromstring(input); + ICharStream stream = CharStreams.fromString(input); ITokenSource lexer = new MiniSQLLexer(stream); ITokenStream tokens = new CommonTokenStream(lexer); MiniSQLParser parser = new MiniSQLParser(tokens); diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL.g4 b/src/MiniSQL.Interpreter/Grammar/MiniSQL.g4 index 74ea5ff..30cd4f2 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL.g4 +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL.g4 @@ -52,6 +52,7 @@ simpleStatement: | quitStatement | execFileStatement + | showTablesStatement ; quitStatement: @@ -62,6 +63,10 @@ execFileStatement: EXECFILE_SYMBOL (SINGLE_QUOTED_TEXT | DOUBLE_QUOTED_TEXT) ; +showTablesStatement: + SHOW_SYMBOL TABLES_SYMBOL +; + createStatement: CREATE_SYMBOL ( createTable @@ -323,6 +328,7 @@ DECIMAL_NUMBER: DIGITS? DOT_SYMBOL DIGITS; FLOAT_NUMBER: (DIGITS? DOT_SYMBOL)? DIGITS [eE] (MINUS_OPERATOR | PLUS_OPERATOR)? DIGITS; +SHOW_SYMBOL: S H O W; // Custom EXECFILE_SYMBOL: E X E C F I L E; // Custom QUIT_SYMBOL: Q U I T; // Custom AND_SYMBOL: A N D; // SQL-2003-R diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.interp b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.interp index fd7a66a..a42fcca 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.interp +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.interp @@ -38,6 +38,7 @@ null null null null +null '=' ':=' '<=>' @@ -86,6 +87,7 @@ BIN_NUMBER INT_NUMBER DECIMAL_NUMBER FLOAT_NUMBER +SHOW_SYMBOL EXECFILE_SYMBOL QUIT_SYMBOL AND_SYMBOL @@ -165,6 +167,7 @@ prog simpleStatement quitStatement execFileStatement +showTablesStatement createStatement createTable createIndex @@ -209,4 +212,4 @@ variable atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 80, 326, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 3, 2, 3, 2, 3, 2, 3, 2, 6, 2, 97, 10, 2, 13, 2, 14, 2, 98, 3, 2, 3, 2, 5, 2, 103, 10, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 113, 10, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 5, 6, 123, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 131, 10, 7, 3, 8, 5, 8, 134, 10, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 5, 9, 143, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 149, 10, 10, 3, 11, 3, 11, 5, 11, 153, 10, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 5, 12, 160, 10, 12, 3, 13, 3, 13, 3, 13, 5, 13, 165, 10, 13, 3, 13, 5, 13, 168, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 5, 15, 176, 10, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 5, 16, 184, 10, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 5, 19, 194, 10, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 7, 20, 201, 10, 20, 12, 20, 14, 20, 204, 11, 20, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 7, 22, 212, 10, 22, 12, 22, 14, 22, 215, 11, 22, 3, 23, 3, 23, 5, 23, 219, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 7, 26, 231, 10, 26, 12, 26, 14, 26, 234, 11, 26, 3, 27, 3, 27, 3, 27, 3, 27, 5, 27, 240, 10, 27, 5, 27, 242, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 5, 29, 250, 10, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 290, 10, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 7, 42, 311, 10, 42, 12, 42, 14, 42, 314, 11, 42, 3, 43, 3, 43, 3, 44, 3, 44, 5, 44, 320, 10, 44, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 2, 3, 82, 47, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 2, 11, 3, 2, 75, 76, 3, 2, 33, 34, 3, 2, 36, 37, 3, 2, 49, 50, 3, 2, 51, 52, 4, 2, 10, 10, 58, 58, 4, 2, 30, 30, 61, 61, 4, 2, 41, 41, 44, 48, 4, 2, 5, 6, 75, 76, 2, 319, 2, 102, 3, 2, 2, 2, 4, 112, 3, 2, 2, 2, 6, 114, 3, 2, 2, 2, 8, 116, 3, 2, 2, 2, 10, 119, 3, 2, 2, 2, 12, 124, 3, 2, 2, 2, 14, 133, 3, 2, 2, 2, 16, 139, 3, 2, 2, 2, 18, 144, 3, 2, 2, 2, 20, 150, 3, 2, 2, 2, 22, 159, 3, 2, 2, 2, 24, 161, 3, 2, 2, 2, 26, 169, 3, 2, 2, 2, 28, 172, 3, 2, 2, 2, 30, 179, 3, 2, 2, 2, 32, 185, 3, 2, 2, 2, 34, 188, 3, 2, 2, 2, 36, 191, 3, 2, 2, 2, 38, 197, 3, 2, 2, 2, 40, 205, 3, 2, 2, 2, 42, 208, 3, 2, 2, 2, 44, 218, 3, 2, 2, 2, 46, 220, 3, 2, 2, 2, 48, 225, 3, 2, 2, 2, 50, 228, 3, 2, 2, 2, 52, 241, 3, 2, 2, 2, 54, 243, 3, 2, 2, 2, 56, 247, 3, 2, 2, 2, 58, 251, 3, 2, 2, 2, 60, 255, 3, 2, 2, 2, 62, 259, 3, 2, 2, 2, 64, 261, 3, 2, 2, 2, 66, 263, 3, 2, 2, 2, 68, 265, 3, 2, 2, 2, 70, 267, 3, 2, 2, 2, 72, 269, 3, 2, 2, 2, 74, 271, 3, 2, 2, 2, 76, 273, 3, 2, 2, 2, 78, 275, 3, 2, 2, 2, 80, 277, 3, 2, 2, 2, 82, 289, 3, 2, 2, 2, 84, 315, 3, 2, 2, 2, 86, 319, 3, 2, 2, 2, 88, 321, 3, 2, 2, 2, 90, 323, 3, 2, 2, 2, 92, 103, 7, 2, 2, 3, 93, 94, 5, 4, 3, 2, 94, 95, 7, 65, 2, 2, 95, 97, 3, 2, 2, 2, 96, 93, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 96, 3, 2, 2, 2, 98, 99, 3, 2, 2, 2, 99, 100, 3, 2, 2, 2, 100, 101, 7, 2, 2, 3, 101, 103, 3, 2, 2, 2, 102, 92, 3, 2, 2, 2, 102, 96, 3, 2, 2, 2, 103, 3, 3, 2, 2, 2, 104, 113, 3, 2, 2, 2, 105, 113, 5, 10, 6, 2, 106, 113, 5, 16, 9, 2, 107, 113, 5, 18, 10, 2, 108, 113, 5, 20, 11, 2, 109, 113, 5, 22, 12, 2, 110, 113, 5, 6, 4, 2, 111, 113, 5, 8, 5, 2, 112, 104, 3, 2, 2, 2, 112, 105, 3, 2, 2, 2, 112, 106, 3, 2, 2, 2, 112, 107, 3, 2, 2, 2, 112, 108, 3, 2, 2, 2, 112, 109, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 112, 111, 3, 2, 2, 2, 113, 5, 3, 2, 2, 2, 114, 115, 7, 9, 2, 2, 115, 7, 3, 2, 2, 2, 116, 117, 7, 8, 2, 2, 117, 118, 9, 2, 2, 2, 118, 9, 3, 2, 2, 2, 119, 122, 7, 16, 2, 2, 120, 123, 5, 12, 7, 2, 121, 123, 5, 14, 8, 2, 122, 120, 3, 2, 2, 2, 122, 121, 3, 2, 2, 2, 123, 11, 3, 2, 2, 2, 124, 125, 7, 34, 2, 2, 125, 130, 5, 62, 32, 2, 126, 127, 7, 67, 2, 2, 127, 128, 5, 42, 22, 2, 128, 129, 7, 68, 2, 2, 129, 131, 3, 2, 2, 2, 130, 126, 3, 2, 2, 2, 130, 131, 3, 2, 2, 2, 131, 13, 3, 2, 2, 2, 132, 134, 7, 35, 2, 2, 133, 132, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 135, 3, 2, 2, 2, 135, 136, 7, 22, 2, 2, 136, 137, 5, 74, 38, 2, 137, 138, 5, 58, 30, 2, 138, 15, 3, 2, 2, 2, 139, 142, 7, 19, 2, 2, 140, 143, 5, 30, 16, 2, 141, 143, 5, 32, 17, 2, 142, 140, 3, 2, 2, 2, 142, 141, 3, 2, 2, 2, 143, 17, 3, 2, 2, 2, 144, 145, 7, 17, 2, 2, 145, 146, 7, 21, 2, 2, 146, 148, 5, 70, 36, 2, 147, 149, 5, 40, 21, 2, 148, 147, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 19, 3, 2, 2, 2, 150, 152, 7, 23, 2, 2, 151, 153, 7, 24, 2, 2, 152, 151, 3, 2, 2, 2, 152, 153, 3, 2, 2, 2, 153, 154, 3, 2, 2, 2, 154, 155, 5, 70, 36, 2, 155, 156, 5, 34, 18, 2, 156, 21, 3, 2, 2, 2, 157, 160, 5, 24, 13, 2, 158, 160, 5, 28, 15, 2, 159, 157, 3, 2, 2, 2, 159, 158, 3, 2, 2, 2, 160, 23, 3, 2, 2, 2, 161, 162, 7, 32, 2, 2, 162, 164, 7, 51, 2, 2, 163, 165, 5, 26, 14, 2, 164, 163, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 167, 3, 2, 2, 2, 166, 168, 5, 40, 21, 2, 167, 166, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 25, 3, 2, 2, 2, 169, 170, 7, 21, 2, 2, 170, 171, 5, 70, 36, 2, 171, 27, 3, 2, 2, 2, 172, 175, 7, 67, 2, 2, 173, 176, 5, 28, 15, 2, 174, 176, 5, 24, 13, 2, 175, 173, 3, 2, 2, 2, 175, 174, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 178, 7, 68, 2, 2, 178, 29, 3, 2, 2, 2, 179, 180, 7, 22, 2, 2, 180, 183, 5, 68, 35, 2, 181, 182, 7, 28, 2, 2, 182, 184, 5, 70, 36, 2, 183, 181, 3, 2, 2, 2, 183, 184, 3, 2, 2, 2, 184, 31, 3, 2, 2, 2, 185, 186, 9, 3, 2, 2, 186, 187, 5, 70, 36, 2, 187, 33, 3, 2, 2, 2, 188, 189, 9, 4, 2, 2, 189, 190, 5, 36, 19, 2, 190, 35, 3, 2, 2, 2, 191, 193, 7, 67, 2, 2, 192, 194, 5, 38, 20, 2, 193, 192, 3, 2, 2, 2, 193, 194, 3, 2, 2, 2, 194, 195, 3, 2, 2, 2, 195, 196, 7, 68, 2, 2, 196, 37, 3, 2, 2, 2, 197, 202, 5, 82, 42, 2, 198, 199, 7, 64, 2, 2, 199, 201, 5, 82, 42, 2, 200, 198, 3, 2, 2, 2, 201, 204, 3, 2, 2, 2, 202, 200, 3, 2, 2, 2, 202, 203, 3, 2, 2, 2, 203, 39, 3, 2, 2, 2, 204, 202, 3, 2, 2, 2, 205, 206, 7, 38, 2, 2, 206, 207, 5, 82, 42, 2, 207, 41, 3, 2, 2, 2, 208, 213, 5, 44, 23, 2, 209, 210, 7, 64, 2, 2, 210, 212, 5, 44, 23, 2, 211, 209, 3, 2, 2, 2, 212, 215, 3, 2, 2, 2, 213, 211, 3, 2, 2, 2, 213, 214, 3, 2, 2, 2, 214, 43, 3, 2, 2, 2, 215, 213, 3, 2, 2, 2, 216, 219, 5, 48, 25, 2, 217, 219, 5, 46, 24, 2, 218, 216, 3, 2, 2, 2, 218, 217, 3, 2, 2, 2, 219, 45, 3, 2, 2, 2, 220, 221, 7, 31, 2, 2, 221, 222, 7, 26, 2, 2, 222, 223, 3, 2, 2, 2, 223, 224, 5, 60, 31, 2, 224, 47, 3, 2, 2, 2, 225, 226, 5, 64, 33, 2, 226, 227, 5, 50, 26, 2, 227, 49, 3, 2, 2, 2, 228, 232, 5, 52, 27, 2, 229, 231, 5, 56, 29, 2, 230, 229, 3, 2, 2, 2, 231, 234, 3, 2, 2, 2, 232, 230, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 51, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 235, 242, 7, 25, 2, 2, 236, 242, 7, 20, 2, 2, 237, 239, 7, 15, 2, 2, 238, 240, 5, 54, 28, 2, 239, 238, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 242, 3, 2, 2, 2, 241, 235, 3, 2, 2, 2, 241, 236, 3, 2, 2, 2, 241, 237, 3, 2, 2, 2, 242, 53, 3, 2, 2, 2, 243, 244, 7, 67, 2, 2, 244, 245, 7, 5, 2, 2, 245, 246, 7, 68, 2, 2, 246, 55, 3, 2, 2, 2, 247, 249, 7, 35, 2, 2, 248, 250, 7, 26, 2, 2, 249, 248, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 57, 3, 2, 2, 2, 251, 252, 7, 28, 2, 2, 252, 253, 5, 70, 36, 2, 253, 254, 5, 60, 31, 2, 254, 59, 3, 2, 2, 2, 255, 256, 7, 67, 2, 2, 256, 257, 5, 66, 34, 2, 257, 258, 7, 68, 2, 2, 258, 61, 3, 2, 2, 2, 259, 260, 5, 80, 41, 2, 260, 63, 3, 2, 2, 2, 261, 262, 5, 72, 37, 2, 262, 65, 3, 2, 2, 2, 263, 264, 5, 78, 40, 2, 264, 67, 3, 2, 2, 2, 265, 266, 5, 72, 37, 2, 266, 69, 3, 2, 2, 2, 267, 268, 5, 80, 41, 2, 268, 71, 3, 2, 2, 2, 269, 270, 5, 80, 41, 2, 270, 73, 3, 2, 2, 2, 271, 272, 5, 78, 40, 2, 272, 75, 3, 2, 2, 2, 273, 274, 7, 73, 2, 2, 274, 77, 3, 2, 2, 2, 275, 276, 5, 76, 39, 2, 276, 79, 3, 2, 2, 2, 277, 278, 5, 78, 40, 2, 278, 81, 3, 2, 2, 2, 279, 280, 8, 42, 1, 2, 280, 281, 7, 67, 2, 2, 281, 282, 5, 82, 42, 2, 282, 283, 7, 68, 2, 2, 283, 290, 3, 2, 2, 2, 284, 285, 9, 5, 2, 2, 285, 290, 5, 82, 42, 11, 286, 287, 7, 27, 2, 2, 287, 290, 5, 82, 42, 10, 288, 290, 5, 86, 44, 2, 289, 279, 3, 2, 2, 2, 289, 284, 3, 2, 2, 2, 289, 286, 3, 2, 2, 2, 289, 288, 3, 2, 2, 2, 290, 312, 3, 2, 2, 2, 291, 292, 12, 9, 2, 2, 292, 293, 9, 6, 2, 2, 293, 311, 5, 82, 42, 10, 294, 295, 12, 8, 2, 2, 295, 296, 9, 5, 2, 2, 296, 311, 5, 82, 42, 9, 297, 298, 12, 7, 2, 2, 298, 299, 5, 84, 43, 2, 299, 300, 5, 82, 42, 8, 300, 311, 3, 2, 2, 2, 301, 302, 12, 6, 2, 2, 302, 303, 9, 7, 2, 2, 303, 311, 5, 82, 42, 7, 304, 305, 12, 5, 2, 2, 305, 306, 7, 40, 2, 2, 306, 311, 5, 82, 42, 6, 307, 308, 12, 4, 2, 2, 308, 309, 9, 8, 2, 2, 309, 311, 5, 82, 42, 5, 310, 291, 3, 2, 2, 2, 310, 294, 3, 2, 2, 2, 310, 297, 3, 2, 2, 2, 310, 301, 3, 2, 2, 2, 310, 304, 3, 2, 2, 2, 310, 307, 3, 2, 2, 2, 311, 314, 3, 2, 2, 2, 312, 310, 3, 2, 2, 2, 312, 313, 3, 2, 2, 2, 313, 83, 3, 2, 2, 2, 314, 312, 3, 2, 2, 2, 315, 316, 9, 9, 2, 2, 316, 85, 3, 2, 2, 2, 317, 320, 5, 88, 45, 2, 318, 320, 5, 90, 46, 2, 319, 317, 3, 2, 2, 2, 319, 318, 3, 2, 2, 2, 320, 87, 3, 2, 2, 2, 321, 322, 9, 10, 2, 2, 322, 89, 3, 2, 2, 2, 323, 324, 5, 78, 40, 2, 324, 91, 3, 2, 2, 2, 28, 98, 102, 112, 122, 130, 133, 142, 148, 152, 159, 164, 167, 175, 183, 193, 202, 213, 218, 232, 239, 241, 249, 289, 310, 312, 319] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 81, 332, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 3, 2, 3, 2, 3, 2, 3, 2, 6, 2, 99, 10, 2, 13, 2, 14, 2, 100, 3, 2, 3, 2, 5, 2, 105, 10, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 116, 10, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 5, 7, 129, 10, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 137, 10, 8, 3, 9, 5, 9, 140, 10, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 5, 10, 149, 10, 10, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 155, 10, 11, 3, 12, 3, 12, 5, 12, 159, 10, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 5, 13, 166, 10, 13, 3, 14, 3, 14, 3, 14, 5, 14, 171, 10, 14, 3, 14, 5, 14, 174, 10, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 5, 16, 182, 10, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 5, 17, 190, 10, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 5, 20, 200, 10, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 7, 21, 207, 10, 21, 12, 21, 14, 21, 210, 11, 21, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 7, 23, 218, 10, 23, 12, 23, 14, 23, 221, 11, 23, 3, 24, 3, 24, 5, 24, 225, 10, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 7, 27, 237, 10, 27, 12, 27, 14, 27, 240, 11, 27, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 246, 10, 28, 5, 28, 248, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 5, 30, 256, 10, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 5, 43, 296, 10, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 7, 43, 317, 10, 43, 12, 43, 14, 43, 320, 11, 43, 3, 44, 3, 44, 3, 45, 3, 45, 5, 45, 326, 10, 45, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 2, 3, 84, 48, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 2, 11, 3, 2, 76, 77, 3, 2, 34, 35, 3, 2, 37, 38, 3, 2, 50, 51, 3, 2, 52, 53, 4, 2, 11, 11, 59, 59, 4, 2, 31, 31, 62, 62, 4, 2, 42, 42, 45, 49, 4, 2, 5, 6, 76, 77, 2, 325, 2, 104, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 6, 117, 3, 2, 2, 2, 8, 119, 3, 2, 2, 2, 10, 122, 3, 2, 2, 2, 12, 125, 3, 2, 2, 2, 14, 130, 3, 2, 2, 2, 16, 139, 3, 2, 2, 2, 18, 145, 3, 2, 2, 2, 20, 150, 3, 2, 2, 2, 22, 156, 3, 2, 2, 2, 24, 165, 3, 2, 2, 2, 26, 167, 3, 2, 2, 2, 28, 175, 3, 2, 2, 2, 30, 178, 3, 2, 2, 2, 32, 185, 3, 2, 2, 2, 34, 191, 3, 2, 2, 2, 36, 194, 3, 2, 2, 2, 38, 197, 3, 2, 2, 2, 40, 203, 3, 2, 2, 2, 42, 211, 3, 2, 2, 2, 44, 214, 3, 2, 2, 2, 46, 224, 3, 2, 2, 2, 48, 226, 3, 2, 2, 2, 50, 231, 3, 2, 2, 2, 52, 234, 3, 2, 2, 2, 54, 247, 3, 2, 2, 2, 56, 249, 3, 2, 2, 2, 58, 253, 3, 2, 2, 2, 60, 257, 3, 2, 2, 2, 62, 261, 3, 2, 2, 2, 64, 265, 3, 2, 2, 2, 66, 267, 3, 2, 2, 2, 68, 269, 3, 2, 2, 2, 70, 271, 3, 2, 2, 2, 72, 273, 3, 2, 2, 2, 74, 275, 3, 2, 2, 2, 76, 277, 3, 2, 2, 2, 78, 279, 3, 2, 2, 2, 80, 281, 3, 2, 2, 2, 82, 283, 3, 2, 2, 2, 84, 295, 3, 2, 2, 2, 86, 321, 3, 2, 2, 2, 88, 325, 3, 2, 2, 2, 90, 327, 3, 2, 2, 2, 92, 329, 3, 2, 2, 2, 94, 105, 7, 2, 2, 3, 95, 96, 5, 4, 3, 2, 96, 97, 7, 66, 2, 2, 97, 99, 3, 2, 2, 2, 98, 95, 3, 2, 2, 2, 99, 100, 3, 2, 2, 2, 100, 98, 3, 2, 2, 2, 100, 101, 3, 2, 2, 2, 101, 102, 3, 2, 2, 2, 102, 103, 7, 2, 2, 3, 103, 105, 3, 2, 2, 2, 104, 94, 3, 2, 2, 2, 104, 98, 3, 2, 2, 2, 105, 3, 3, 2, 2, 2, 106, 116, 3, 2, 2, 2, 107, 116, 5, 12, 7, 2, 108, 116, 5, 18, 10, 2, 109, 116, 5, 20, 11, 2, 110, 116, 5, 22, 12, 2, 111, 116, 5, 24, 13, 2, 112, 116, 5, 6, 4, 2, 113, 116, 5, 8, 5, 2, 114, 116, 5, 10, 6, 2, 115, 106, 3, 2, 2, 2, 115, 107, 3, 2, 2, 2, 115, 108, 3, 2, 2, 2, 115, 109, 3, 2, 2, 2, 115, 110, 3, 2, 2, 2, 115, 111, 3, 2, 2, 2, 115, 112, 3, 2, 2, 2, 115, 113, 3, 2, 2, 2, 115, 114, 3, 2, 2, 2, 116, 5, 3, 2, 2, 2, 117, 118, 7, 10, 2, 2, 118, 7, 3, 2, 2, 2, 119, 120, 7, 9, 2, 2, 120, 121, 9, 2, 2, 2, 121, 9, 3, 2, 2, 2, 122, 123, 7, 8, 2, 2, 123, 124, 7, 34, 2, 2, 124, 11, 3, 2, 2, 2, 125, 128, 7, 17, 2, 2, 126, 129, 5, 14, 8, 2, 127, 129, 5, 16, 9, 2, 128, 126, 3, 2, 2, 2, 128, 127, 3, 2, 2, 2, 129, 13, 3, 2, 2, 2, 130, 131, 7, 35, 2, 2, 131, 136, 5, 64, 33, 2, 132, 133, 7, 68, 2, 2, 133, 134, 5, 44, 23, 2, 134, 135, 7, 69, 2, 2, 135, 137, 3, 2, 2, 2, 136, 132, 3, 2, 2, 2, 136, 137, 3, 2, 2, 2, 137, 15, 3, 2, 2, 2, 138, 140, 7, 36, 2, 2, 139, 138, 3, 2, 2, 2, 139, 140, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 142, 7, 23, 2, 2, 142, 143, 5, 76, 39, 2, 143, 144, 5, 60, 31, 2, 144, 17, 3, 2, 2, 2, 145, 148, 7, 20, 2, 2, 146, 149, 5, 32, 17, 2, 147, 149, 5, 34, 18, 2, 148, 146, 3, 2, 2, 2, 148, 147, 3, 2, 2, 2, 149, 19, 3, 2, 2, 2, 150, 151, 7, 18, 2, 2, 151, 152, 7, 22, 2, 2, 152, 154, 5, 72, 37, 2, 153, 155, 5, 42, 22, 2, 154, 153, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 21, 3, 2, 2, 2, 156, 158, 7, 24, 2, 2, 157, 159, 7, 25, 2, 2, 158, 157, 3, 2, 2, 2, 158, 159, 3, 2, 2, 2, 159, 160, 3, 2, 2, 2, 160, 161, 5, 72, 37, 2, 161, 162, 5, 36, 19, 2, 162, 23, 3, 2, 2, 2, 163, 166, 5, 26, 14, 2, 164, 166, 5, 30, 16, 2, 165, 163, 3, 2, 2, 2, 165, 164, 3, 2, 2, 2, 166, 25, 3, 2, 2, 2, 167, 168, 7, 33, 2, 2, 168, 170, 7, 52, 2, 2, 169, 171, 5, 28, 15, 2, 170, 169, 3, 2, 2, 2, 170, 171, 3, 2, 2, 2, 171, 173, 3, 2, 2, 2, 172, 174, 5, 42, 22, 2, 173, 172, 3, 2, 2, 2, 173, 174, 3, 2, 2, 2, 174, 27, 3, 2, 2, 2, 175, 176, 7, 22, 2, 2, 176, 177, 5, 72, 37, 2, 177, 29, 3, 2, 2, 2, 178, 181, 7, 68, 2, 2, 179, 182, 5, 30, 16, 2, 180, 182, 5, 26, 14, 2, 181, 179, 3, 2, 2, 2, 181, 180, 3, 2, 2, 2, 182, 183, 3, 2, 2, 2, 183, 184, 7, 69, 2, 2, 184, 31, 3, 2, 2, 2, 185, 186, 7, 23, 2, 2, 186, 189, 5, 70, 36, 2, 187, 188, 7, 29, 2, 2, 188, 190, 5, 72, 37, 2, 189, 187, 3, 2, 2, 2, 189, 190, 3, 2, 2, 2, 190, 33, 3, 2, 2, 2, 191, 192, 9, 3, 2, 2, 192, 193, 5, 72, 37, 2, 193, 35, 3, 2, 2, 2, 194, 195, 9, 4, 2, 2, 195, 196, 5, 38, 20, 2, 196, 37, 3, 2, 2, 2, 197, 199, 7, 68, 2, 2, 198, 200, 5, 40, 21, 2, 199, 198, 3, 2, 2, 2, 199, 200, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 202, 7, 69, 2, 2, 202, 39, 3, 2, 2, 2, 203, 208, 5, 84, 43, 2, 204, 205, 7, 65, 2, 2, 205, 207, 5, 84, 43, 2, 206, 204, 3, 2, 2, 2, 207, 210, 3, 2, 2, 2, 208, 206, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 41, 3, 2, 2, 2, 210, 208, 3, 2, 2, 2, 211, 212, 7, 39, 2, 2, 212, 213, 5, 84, 43, 2, 213, 43, 3, 2, 2, 2, 214, 219, 5, 46, 24, 2, 215, 216, 7, 65, 2, 2, 216, 218, 5, 46, 24, 2, 217, 215, 3, 2, 2, 2, 218, 221, 3, 2, 2, 2, 219, 217, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 220, 45, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 222, 225, 5, 50, 26, 2, 223, 225, 5, 48, 25, 2, 224, 222, 3, 2, 2, 2, 224, 223, 3, 2, 2, 2, 225, 47, 3, 2, 2, 2, 226, 227, 7, 32, 2, 2, 227, 228, 7, 27, 2, 2, 228, 229, 3, 2, 2, 2, 229, 230, 5, 62, 32, 2, 230, 49, 3, 2, 2, 2, 231, 232, 5, 66, 34, 2, 232, 233, 5, 52, 27, 2, 233, 51, 3, 2, 2, 2, 234, 238, 5, 54, 28, 2, 235, 237, 5, 58, 30, 2, 236, 235, 3, 2, 2, 2, 237, 240, 3, 2, 2, 2, 238, 236, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 53, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 241, 248, 7, 26, 2, 2, 242, 248, 7, 21, 2, 2, 243, 245, 7, 16, 2, 2, 244, 246, 5, 56, 29, 2, 245, 244, 3, 2, 2, 2, 245, 246, 3, 2, 2, 2, 246, 248, 3, 2, 2, 2, 247, 241, 3, 2, 2, 2, 247, 242, 3, 2, 2, 2, 247, 243, 3, 2, 2, 2, 248, 55, 3, 2, 2, 2, 249, 250, 7, 68, 2, 2, 250, 251, 7, 5, 2, 2, 251, 252, 7, 69, 2, 2, 252, 57, 3, 2, 2, 2, 253, 255, 7, 36, 2, 2, 254, 256, 7, 27, 2, 2, 255, 254, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 59, 3, 2, 2, 2, 257, 258, 7, 29, 2, 2, 258, 259, 5, 72, 37, 2, 259, 260, 5, 62, 32, 2, 260, 61, 3, 2, 2, 2, 261, 262, 7, 68, 2, 2, 262, 263, 5, 68, 35, 2, 263, 264, 7, 69, 2, 2, 264, 63, 3, 2, 2, 2, 265, 266, 5, 82, 42, 2, 266, 65, 3, 2, 2, 2, 267, 268, 5, 74, 38, 2, 268, 67, 3, 2, 2, 2, 269, 270, 5, 80, 41, 2, 270, 69, 3, 2, 2, 2, 271, 272, 5, 74, 38, 2, 272, 71, 3, 2, 2, 2, 273, 274, 5, 82, 42, 2, 274, 73, 3, 2, 2, 2, 275, 276, 5, 82, 42, 2, 276, 75, 3, 2, 2, 2, 277, 278, 5, 80, 41, 2, 278, 77, 3, 2, 2, 2, 279, 280, 7, 74, 2, 2, 280, 79, 3, 2, 2, 2, 281, 282, 5, 78, 40, 2, 282, 81, 3, 2, 2, 2, 283, 284, 5, 80, 41, 2, 284, 83, 3, 2, 2, 2, 285, 286, 8, 43, 1, 2, 286, 287, 7, 68, 2, 2, 287, 288, 5, 84, 43, 2, 288, 289, 7, 69, 2, 2, 289, 296, 3, 2, 2, 2, 290, 291, 9, 5, 2, 2, 291, 296, 5, 84, 43, 11, 292, 293, 7, 28, 2, 2, 293, 296, 5, 84, 43, 10, 294, 296, 5, 88, 45, 2, 295, 285, 3, 2, 2, 2, 295, 290, 3, 2, 2, 2, 295, 292, 3, 2, 2, 2, 295, 294, 3, 2, 2, 2, 296, 318, 3, 2, 2, 2, 297, 298, 12, 9, 2, 2, 298, 299, 9, 6, 2, 2, 299, 317, 5, 84, 43, 10, 300, 301, 12, 8, 2, 2, 301, 302, 9, 5, 2, 2, 302, 317, 5, 84, 43, 9, 303, 304, 12, 7, 2, 2, 304, 305, 5, 86, 44, 2, 305, 306, 5, 84, 43, 8, 306, 317, 3, 2, 2, 2, 307, 308, 12, 6, 2, 2, 308, 309, 9, 7, 2, 2, 309, 317, 5, 84, 43, 7, 310, 311, 12, 5, 2, 2, 311, 312, 7, 41, 2, 2, 312, 317, 5, 84, 43, 6, 313, 314, 12, 4, 2, 2, 314, 315, 9, 8, 2, 2, 315, 317, 5, 84, 43, 5, 316, 297, 3, 2, 2, 2, 316, 300, 3, 2, 2, 2, 316, 303, 3, 2, 2, 2, 316, 307, 3, 2, 2, 2, 316, 310, 3, 2, 2, 2, 316, 313, 3, 2, 2, 2, 317, 320, 3, 2, 2, 2, 318, 316, 3, 2, 2, 2, 318, 319, 3, 2, 2, 2, 319, 85, 3, 2, 2, 2, 320, 318, 3, 2, 2, 2, 321, 322, 9, 9, 2, 2, 322, 87, 3, 2, 2, 2, 323, 326, 5, 90, 46, 2, 324, 326, 5, 92, 47, 2, 325, 323, 3, 2, 2, 2, 325, 324, 3, 2, 2, 2, 326, 89, 3, 2, 2, 2, 327, 328, 9, 10, 2, 2, 328, 91, 3, 2, 2, 2, 329, 330, 5, 80, 41, 2, 330, 93, 3, 2, 2, 2, 28, 100, 104, 115, 128, 136, 139, 148, 154, 158, 165, 170, 173, 181, 189, 199, 208, 219, 224, 238, 245, 247, 255, 295, 316, 318, 325] \ No newline at end of file diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.tokens b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.tokens index 812dcb3..4df5972 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.tokens +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQL.tokens @@ -3,108 +3,109 @@ BIN_NUMBER=2 INT_NUMBER=3 DECIMAL_NUMBER=4 FLOAT_NUMBER=5 -EXECFILE_SYMBOL=6 -QUIT_SYMBOL=7 -AND_SYMBOL=8 -ASC_SYMBOL=9 -AS_SYMBOL=10 -BEGIN_SYMBOL=11 -BY_SYMBOL=12 -CHAR_SYMBOL=13 -CREATE_SYMBOL=14 -DELETE_SYMBOL=15 -DESC_SYMBOL=16 -DROP_SYMBOL=17 -FLOAT_SYMBOL=18 -FROM_SYMBOL=19 -INDEX_SYMBOL=20 -INSERT_SYMBOL=21 -INTO_SYMBOL=22 -INT_SYMBOL=23 -KEY_SYMBOL=24 -NOT_SYMBOL=25 -ON_SYMBOL=26 -ORDER_SYMBOL=27 -OR_SYMBOL=28 -PRIMARY_SYMBOL=29 -SELECT_SYMBOL=30 -TABLES_SYMBOL=31 -TABLE_SYMBOL=32 -UNIQUE_SYMBOL=33 -VALUES_SYMBOL=34 -VALUE_SYMBOL=35 -WHERE_SYMBOL=36 -WORK_SYMBOL=37 -XOR_SYMBOL=38 -EQUAL_OPERATOR=39 -ASSIGN_OPERATOR=40 -NULL_SAFE_EQUAL_OPERATOR=41 -GREATER_OR_EQUAL_OPERATOR=42 -GREATER_THAN_OPERATOR=43 -LESS_OR_EQUAL_OPERATOR=44 -LESS_THAN_OPERATOR=45 -NOT_EQUAL_OPERATOR=46 -PLUS_OPERATOR=47 -MINUS_OPERATOR=48 -MULT_OPERATOR=49 -DIV_OPERATOR=50 -MOD_OPERATOR=51 -LOGICAL_NOT_OPERATOR=52 -BITWISE_NOT_OPERATOR=53 -SHIFT_LEFT_OPERATOR=54 -SHIFT_RIGHT_OPERATOR=55 -LOGICAL_AND_OPERATOR=56 -BITWISE_AND_OPERATOR=57 -BITWISE_XOR_OPERATOR=58 -LOGICAL_OR_OPERATOR=59 -BITWISE_OR_OPERATOR=60 -DOT_SYMBOL=61 -COMMA_SYMBOL=62 -SEMICOLON_SYMBOL=63 -COLON_SYMBOL=64 -OPEN_PAR_SYMBOL=65 -CLOSE_PAR_SYMBOL=66 -OPEN_CURLY_SYMBOL=67 -CLOSE_CURLY_SYMBOL=68 -UNDERLINE_SYMBOL=69 -WHITESPACE=70 -IDENTIFIER=71 -NCHAR_TEXT=72 -DOUBLE_QUOTED_TEXT=73 -SINGLE_QUOTED_TEXT=74 -BLOCK_COMMENT=75 -POUND_COMMENT=76 -DASHDASH_COMMENT=77 -NOT_EQUAL2_OPERATOR=78 -'='=39 -':='=40 -'<=>'=41 -'>='=42 -'>'=43 -'<='=44 -'<'=45 -'!='=46 -''=78 -'+'=47 -'-'=48 -'*'=49 -'/'=50 -'%'=51 -'!'=52 -'~'=53 -'<<'=54 -'>>'=55 -'&&'=56 -'&'=57 -'^'=58 -'||'=59 -'|'=60 -'.'=61 -','=62 -';'=63 -':'=64 -'('=65 -')'=66 -'{'=67 -'}'=68 -'_'=69 +SHOW_SYMBOL=6 +EXECFILE_SYMBOL=7 +QUIT_SYMBOL=8 +AND_SYMBOL=9 +ASC_SYMBOL=10 +AS_SYMBOL=11 +BEGIN_SYMBOL=12 +BY_SYMBOL=13 +CHAR_SYMBOL=14 +CREATE_SYMBOL=15 +DELETE_SYMBOL=16 +DESC_SYMBOL=17 +DROP_SYMBOL=18 +FLOAT_SYMBOL=19 +FROM_SYMBOL=20 +INDEX_SYMBOL=21 +INSERT_SYMBOL=22 +INTO_SYMBOL=23 +INT_SYMBOL=24 +KEY_SYMBOL=25 +NOT_SYMBOL=26 +ON_SYMBOL=27 +ORDER_SYMBOL=28 +OR_SYMBOL=29 +PRIMARY_SYMBOL=30 +SELECT_SYMBOL=31 +TABLES_SYMBOL=32 +TABLE_SYMBOL=33 +UNIQUE_SYMBOL=34 +VALUES_SYMBOL=35 +VALUE_SYMBOL=36 +WHERE_SYMBOL=37 +WORK_SYMBOL=38 +XOR_SYMBOL=39 +EQUAL_OPERATOR=40 +ASSIGN_OPERATOR=41 +NULL_SAFE_EQUAL_OPERATOR=42 +GREATER_OR_EQUAL_OPERATOR=43 +GREATER_THAN_OPERATOR=44 +LESS_OR_EQUAL_OPERATOR=45 +LESS_THAN_OPERATOR=46 +NOT_EQUAL_OPERATOR=47 +PLUS_OPERATOR=48 +MINUS_OPERATOR=49 +MULT_OPERATOR=50 +DIV_OPERATOR=51 +MOD_OPERATOR=52 +LOGICAL_NOT_OPERATOR=53 +BITWISE_NOT_OPERATOR=54 +SHIFT_LEFT_OPERATOR=55 +SHIFT_RIGHT_OPERATOR=56 +LOGICAL_AND_OPERATOR=57 +BITWISE_AND_OPERATOR=58 +BITWISE_XOR_OPERATOR=59 +LOGICAL_OR_OPERATOR=60 +BITWISE_OR_OPERATOR=61 +DOT_SYMBOL=62 +COMMA_SYMBOL=63 +SEMICOLON_SYMBOL=64 +COLON_SYMBOL=65 +OPEN_PAR_SYMBOL=66 +CLOSE_PAR_SYMBOL=67 +OPEN_CURLY_SYMBOL=68 +CLOSE_CURLY_SYMBOL=69 +UNDERLINE_SYMBOL=70 +WHITESPACE=71 +IDENTIFIER=72 +NCHAR_TEXT=73 +DOUBLE_QUOTED_TEXT=74 +SINGLE_QUOTED_TEXT=75 +BLOCK_COMMENT=76 +POUND_COMMENT=77 +DASHDASH_COMMENT=78 +NOT_EQUAL2_OPERATOR=79 +'='=40 +':='=41 +'<=>'=42 +'>='=43 +'>'=44 +'<='=45 +'<'=46 +'!='=47 +''=79 +'+'=48 +'-'=49 +'*'=50 +'/'=51 +'%'=52 +'!'=53 +'~'=54 +'<<'=55 +'>>'=56 +'&&'=57 +'&'=58 +'^'=59 +'||'=60 +'|'=61 +'.'=62 +','=63 +';'=64 +':'=65 +'('=66 +')'=67 +'{'=68 +'}'=69 +'_'=70 diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseListener.cs b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseListener.cs index 2812d4e..fe8fdb4 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseListener.cs +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseListener.cs @@ -83,6 +83,18 @@ public virtual void EnterExecFileStatement([NotNull] MiniSQLParser.ExecFileState /// The parse tree. public virtual void ExitExecFileStatement([NotNull] MiniSQLParser.ExecFileStatementContext context) { } /// + /// Enter a parse tree produced by . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context) { } + /// + /// Exit a parse tree produced by . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context) { } + /// /// Enter a parse tree produced by . /// The default implementation does nothing. /// diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseVisitor.cs b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseVisitor.cs index 0b5d87f..fa589b5 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseVisitor.cs +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLBaseVisitor.cs @@ -74,6 +74,16 @@ public partial class MiniSQLBaseVisitor : AbstractParseTreeVisitorThe visitor result. public virtual Result VisitExecFileStatement([NotNull] MiniSQLParser.ExecFileStatementContext context) { return VisitChildren(context); } /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context) { return VisitChildren(context); } + /// /// Visit a parse tree produced by . /// /// The default implementation returns the result of calling diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.cs b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.cs index 3a42b3e..d192066 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.cs +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.cs @@ -34,24 +34,24 @@ public partial class MiniSQLLexer : Lexer { protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); public const int HEX_NUMBER=1, BIN_NUMBER=2, INT_NUMBER=3, DECIMAL_NUMBER=4, FLOAT_NUMBER=5, - EXECFILE_SYMBOL=6, QUIT_SYMBOL=7, AND_SYMBOL=8, ASC_SYMBOL=9, AS_SYMBOL=10, - BEGIN_SYMBOL=11, BY_SYMBOL=12, CHAR_SYMBOL=13, CREATE_SYMBOL=14, DELETE_SYMBOL=15, - DESC_SYMBOL=16, DROP_SYMBOL=17, FLOAT_SYMBOL=18, FROM_SYMBOL=19, INDEX_SYMBOL=20, - INSERT_SYMBOL=21, INTO_SYMBOL=22, INT_SYMBOL=23, KEY_SYMBOL=24, NOT_SYMBOL=25, - ON_SYMBOL=26, ORDER_SYMBOL=27, OR_SYMBOL=28, PRIMARY_SYMBOL=29, SELECT_SYMBOL=30, - TABLES_SYMBOL=31, TABLE_SYMBOL=32, UNIQUE_SYMBOL=33, VALUES_SYMBOL=34, - VALUE_SYMBOL=35, WHERE_SYMBOL=36, WORK_SYMBOL=37, XOR_SYMBOL=38, EQUAL_OPERATOR=39, - ASSIGN_OPERATOR=40, NULL_SAFE_EQUAL_OPERATOR=41, GREATER_OR_EQUAL_OPERATOR=42, - GREATER_THAN_OPERATOR=43, LESS_OR_EQUAL_OPERATOR=44, LESS_THAN_OPERATOR=45, - NOT_EQUAL_OPERATOR=46, PLUS_OPERATOR=47, MINUS_OPERATOR=48, MULT_OPERATOR=49, - DIV_OPERATOR=50, MOD_OPERATOR=51, LOGICAL_NOT_OPERATOR=52, BITWISE_NOT_OPERATOR=53, - SHIFT_LEFT_OPERATOR=54, SHIFT_RIGHT_OPERATOR=55, LOGICAL_AND_OPERATOR=56, - BITWISE_AND_OPERATOR=57, BITWISE_XOR_OPERATOR=58, LOGICAL_OR_OPERATOR=59, - BITWISE_OR_OPERATOR=60, DOT_SYMBOL=61, COMMA_SYMBOL=62, SEMICOLON_SYMBOL=63, - COLON_SYMBOL=64, OPEN_PAR_SYMBOL=65, CLOSE_PAR_SYMBOL=66, OPEN_CURLY_SYMBOL=67, - CLOSE_CURLY_SYMBOL=68, UNDERLINE_SYMBOL=69, WHITESPACE=70, IDENTIFIER=71, - NCHAR_TEXT=72, DOUBLE_QUOTED_TEXT=73, SINGLE_QUOTED_TEXT=74, BLOCK_COMMENT=75, - POUND_COMMENT=76, DASHDASH_COMMENT=77, NOT_EQUAL2_OPERATOR=78; + SHOW_SYMBOL=6, EXECFILE_SYMBOL=7, QUIT_SYMBOL=8, AND_SYMBOL=9, ASC_SYMBOL=10, + AS_SYMBOL=11, BEGIN_SYMBOL=12, BY_SYMBOL=13, CHAR_SYMBOL=14, CREATE_SYMBOL=15, + DELETE_SYMBOL=16, DESC_SYMBOL=17, DROP_SYMBOL=18, FLOAT_SYMBOL=19, FROM_SYMBOL=20, + INDEX_SYMBOL=21, INSERT_SYMBOL=22, INTO_SYMBOL=23, INT_SYMBOL=24, KEY_SYMBOL=25, + NOT_SYMBOL=26, ON_SYMBOL=27, ORDER_SYMBOL=28, OR_SYMBOL=29, PRIMARY_SYMBOL=30, + SELECT_SYMBOL=31, TABLES_SYMBOL=32, TABLE_SYMBOL=33, UNIQUE_SYMBOL=34, + VALUES_SYMBOL=35, VALUE_SYMBOL=36, WHERE_SYMBOL=37, WORK_SYMBOL=38, XOR_SYMBOL=39, + EQUAL_OPERATOR=40, ASSIGN_OPERATOR=41, NULL_SAFE_EQUAL_OPERATOR=42, GREATER_OR_EQUAL_OPERATOR=43, + GREATER_THAN_OPERATOR=44, LESS_OR_EQUAL_OPERATOR=45, LESS_THAN_OPERATOR=46, + NOT_EQUAL_OPERATOR=47, PLUS_OPERATOR=48, MINUS_OPERATOR=49, MULT_OPERATOR=50, + DIV_OPERATOR=51, MOD_OPERATOR=52, LOGICAL_NOT_OPERATOR=53, BITWISE_NOT_OPERATOR=54, + SHIFT_LEFT_OPERATOR=55, SHIFT_RIGHT_OPERATOR=56, LOGICAL_AND_OPERATOR=57, + BITWISE_AND_OPERATOR=58, BITWISE_XOR_OPERATOR=59, LOGICAL_OR_OPERATOR=60, + BITWISE_OR_OPERATOR=61, DOT_SYMBOL=62, COMMA_SYMBOL=63, SEMICOLON_SYMBOL=64, + COLON_SYMBOL=65, OPEN_PAR_SYMBOL=66, CLOSE_PAR_SYMBOL=67, OPEN_CURLY_SYMBOL=68, + CLOSE_CURLY_SYMBOL=69, UNDERLINE_SYMBOL=70, WHITESPACE=71, IDENTIFIER=72, + NCHAR_TEXT=73, DOUBLE_QUOTED_TEXT=74, SINGLE_QUOTED_TEXT=75, BLOCK_COMMENT=76, + POUND_COMMENT=77, DASHDASH_COMMENT=78, NOT_EQUAL2_OPERATOR=79; public static string[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -64,14 +64,14 @@ public const int "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "DIGIT", "DIGITS", "HEXDIGIT", "HEX_NUMBER", "BIN_NUMBER", "INT_NUMBER", "DECIMAL_NUMBER", - "FLOAT_NUMBER", "EXECFILE_SYMBOL", "QUIT_SYMBOL", "AND_SYMBOL", "ASC_SYMBOL", - "AS_SYMBOL", "BEGIN_SYMBOL", "BY_SYMBOL", "CHAR_SYMBOL", "CREATE_SYMBOL", - "DELETE_SYMBOL", "DESC_SYMBOL", "DROP_SYMBOL", "FLOAT_SYMBOL", "FROM_SYMBOL", - "INDEX_SYMBOL", "INSERT_SYMBOL", "INTO_SYMBOL", "INT_SYMBOL", "KEY_SYMBOL", - "NOT_SYMBOL", "ON_SYMBOL", "ORDER_SYMBOL", "OR_SYMBOL", "PRIMARY_SYMBOL", - "SELECT_SYMBOL", "TABLES_SYMBOL", "TABLE_SYMBOL", "UNIQUE_SYMBOL", "VALUES_SYMBOL", - "VALUE_SYMBOL", "WHERE_SYMBOL", "WORK_SYMBOL", "XOR_SYMBOL", "EQUAL_OPERATOR", - "ASSIGN_OPERATOR", "NULL_SAFE_EQUAL_OPERATOR", "GREATER_OR_EQUAL_OPERATOR", + "FLOAT_NUMBER", "SHOW_SYMBOL", "EXECFILE_SYMBOL", "QUIT_SYMBOL", "AND_SYMBOL", + "ASC_SYMBOL", "AS_SYMBOL", "BEGIN_SYMBOL", "BY_SYMBOL", "CHAR_SYMBOL", + "CREATE_SYMBOL", "DELETE_SYMBOL", "DESC_SYMBOL", "DROP_SYMBOL", "FLOAT_SYMBOL", + "FROM_SYMBOL", "INDEX_SYMBOL", "INSERT_SYMBOL", "INTO_SYMBOL", "INT_SYMBOL", + "KEY_SYMBOL", "NOT_SYMBOL", "ON_SYMBOL", "ORDER_SYMBOL", "OR_SYMBOL", + "PRIMARY_SYMBOL", "SELECT_SYMBOL", "TABLES_SYMBOL", "TABLE_SYMBOL", "UNIQUE_SYMBOL", + "VALUES_SYMBOL", "VALUE_SYMBOL", "WHERE_SYMBOL", "WORK_SYMBOL", "XOR_SYMBOL", + "EQUAL_OPERATOR", "ASSIGN_OPERATOR", "NULL_SAFE_EQUAL_OPERATOR", "GREATER_OR_EQUAL_OPERATOR", "GREATER_THAN_OPERATOR", "LESS_OR_EQUAL_OPERATOR", "LESS_THAN_OPERATOR", "NOT_EQUAL_OPERATOR", "NOT_EQUAL2_OPERATOR", "PLUS_OPERATOR", "MINUS_OPERATOR", "MULT_OPERATOR", "DIV_OPERATOR", "MOD_OPERATOR", "LOGICAL_NOT_OPERATOR", @@ -101,31 +101,32 @@ public MiniSQLLexer(ICharStream input, TextWriter output, TextWriter errorOutput null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, "'='", "':='", "'<=>'", "'>='", "'>'", "'<='", "'<'", - "'!='", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "'~'", "'<<'", "'>>'", - "'&&'", "'&'", "'^'", "'||'", "'|'", "'.'", "','", "';'", "':'", "'('", - "')'", "'{'", "'}'", "'_'", null, null, null, null, null, null, null, - null, "''" + null, null, null, null, "'='", "':='", "'<=>'", "'>='", "'>'", "'<='", + "'<'", "'!='", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "'~'", "'<<'", + "'>>'", "'&&'", "'&'", "'^'", "'||'", "'|'", "'.'", "','", "';'", "':'", + "'('", "')'", "'{'", "'}'", "'_'", null, null, null, null, null, null, + null, null, "''" }; private static readonly string[] _SymbolicNames = { null, "HEX_NUMBER", "BIN_NUMBER", "INT_NUMBER", "DECIMAL_NUMBER", "FLOAT_NUMBER", - "EXECFILE_SYMBOL", "QUIT_SYMBOL", "AND_SYMBOL", "ASC_SYMBOL", "AS_SYMBOL", - "BEGIN_SYMBOL", "BY_SYMBOL", "CHAR_SYMBOL", "CREATE_SYMBOL", "DELETE_SYMBOL", - "DESC_SYMBOL", "DROP_SYMBOL", "FLOAT_SYMBOL", "FROM_SYMBOL", "INDEX_SYMBOL", - "INSERT_SYMBOL", "INTO_SYMBOL", "INT_SYMBOL", "KEY_SYMBOL", "NOT_SYMBOL", - "ON_SYMBOL", "ORDER_SYMBOL", "OR_SYMBOL", "PRIMARY_SYMBOL", "SELECT_SYMBOL", - "TABLES_SYMBOL", "TABLE_SYMBOL", "UNIQUE_SYMBOL", "VALUES_SYMBOL", "VALUE_SYMBOL", - "WHERE_SYMBOL", "WORK_SYMBOL", "XOR_SYMBOL", "EQUAL_OPERATOR", "ASSIGN_OPERATOR", - "NULL_SAFE_EQUAL_OPERATOR", "GREATER_OR_EQUAL_OPERATOR", "GREATER_THAN_OPERATOR", - "LESS_OR_EQUAL_OPERATOR", "LESS_THAN_OPERATOR", "NOT_EQUAL_OPERATOR", - "PLUS_OPERATOR", "MINUS_OPERATOR", "MULT_OPERATOR", "DIV_OPERATOR", "MOD_OPERATOR", - "LOGICAL_NOT_OPERATOR", "BITWISE_NOT_OPERATOR", "SHIFT_LEFT_OPERATOR", - "SHIFT_RIGHT_OPERATOR", "LOGICAL_AND_OPERATOR", "BITWISE_AND_OPERATOR", - "BITWISE_XOR_OPERATOR", "LOGICAL_OR_OPERATOR", "BITWISE_OR_OPERATOR", - "DOT_SYMBOL", "COMMA_SYMBOL", "SEMICOLON_SYMBOL", "COLON_SYMBOL", "OPEN_PAR_SYMBOL", - "CLOSE_PAR_SYMBOL", "OPEN_CURLY_SYMBOL", "CLOSE_CURLY_SYMBOL", "UNDERLINE_SYMBOL", - "WHITESPACE", "IDENTIFIER", "NCHAR_TEXT", "DOUBLE_QUOTED_TEXT", "SINGLE_QUOTED_TEXT", - "BLOCK_COMMENT", "POUND_COMMENT", "DASHDASH_COMMENT", "NOT_EQUAL2_OPERATOR" + "SHOW_SYMBOL", "EXECFILE_SYMBOL", "QUIT_SYMBOL", "AND_SYMBOL", "ASC_SYMBOL", + "AS_SYMBOL", "BEGIN_SYMBOL", "BY_SYMBOL", "CHAR_SYMBOL", "CREATE_SYMBOL", + "DELETE_SYMBOL", "DESC_SYMBOL", "DROP_SYMBOL", "FLOAT_SYMBOL", "FROM_SYMBOL", + "INDEX_SYMBOL", "INSERT_SYMBOL", "INTO_SYMBOL", "INT_SYMBOL", "KEY_SYMBOL", + "NOT_SYMBOL", "ON_SYMBOL", "ORDER_SYMBOL", "OR_SYMBOL", "PRIMARY_SYMBOL", + "SELECT_SYMBOL", "TABLES_SYMBOL", "TABLE_SYMBOL", "UNIQUE_SYMBOL", "VALUES_SYMBOL", + "VALUE_SYMBOL", "WHERE_SYMBOL", "WORK_SYMBOL", "XOR_SYMBOL", "EQUAL_OPERATOR", + "ASSIGN_OPERATOR", "NULL_SAFE_EQUAL_OPERATOR", "GREATER_OR_EQUAL_OPERATOR", + "GREATER_THAN_OPERATOR", "LESS_OR_EQUAL_OPERATOR", "LESS_THAN_OPERATOR", + "NOT_EQUAL_OPERATOR", "PLUS_OPERATOR", "MINUS_OPERATOR", "MULT_OPERATOR", + "DIV_OPERATOR", "MOD_OPERATOR", "LOGICAL_NOT_OPERATOR", "BITWISE_NOT_OPERATOR", + "SHIFT_LEFT_OPERATOR", "SHIFT_RIGHT_OPERATOR", "LOGICAL_AND_OPERATOR", + "BITWISE_AND_OPERATOR", "BITWISE_XOR_OPERATOR", "LOGICAL_OR_OPERATOR", + "BITWISE_OR_OPERATOR", "DOT_SYMBOL", "COMMA_SYMBOL", "SEMICOLON_SYMBOL", + "COLON_SYMBOL", "OPEN_PAR_SYMBOL", "CLOSE_PAR_SYMBOL", "OPEN_CURLY_SYMBOL", + "CLOSE_CURLY_SYMBOL", "UNDERLINE_SYMBOL", "WHITESPACE", "IDENTIFIER", + "NCHAR_TEXT", "DOUBLE_QUOTED_TEXT", "SINGLE_QUOTED_TEXT", "BLOCK_COMMENT", + "POUND_COMMENT", "DASHDASH_COMMENT", "NOT_EQUAL2_OPERATOR" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -156,7 +157,7 @@ static MiniSQLLexer() { } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x2', 'P', '\x300', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x5964', '\x2', 'Q', '\x307', '\b', '\x1', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', @@ -197,617 +198,621 @@ static MiniSQLLexer() { '\t', 'm', '\x4', 'n', '\t', 'n', '\x4', 'o', '\t', 'o', '\x4', 'p', '\t', 'p', '\x4', 'q', '\t', 'q', '\x4', 'r', '\t', 'r', '\x4', 's', '\t', 's', '\x4', 't', '\t', 't', '\x4', 'u', '\t', 'u', '\x4', 'v', '\t', 'v', '\x4', - 'w', '\t', 'w', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', - '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', - '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', '\x3', - '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\v', '\x3', '\v', - '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', '\x3', '\xE', '\x3', - '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\x10', '\x3', '\x10', '\x3', - '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x3', - '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x15', '\x3', '\x15', '\x3', - '\x16', '\x3', '\x16', '\x3', '\x17', '\x3', '\x17', '\x3', '\x18', '\x3', - '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', '\x3', '\x1A', '\x3', - '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x6', - '\x1D', '\x127', '\n', '\x1D', '\r', '\x1D', '\xE', '\x1D', '\x128', '\x3', - '\x1E', '\x3', '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', - '\x1F', '\x6', '\x1F', '\x131', '\n', '\x1F', '\r', '\x1F', '\xE', '\x1F', - '\x132', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x6', - '\x1F', '\x139', '\n', '\x1F', '\r', '\x1F', '\xE', '\x1F', '\x13A', '\x3', - '\x1F', '\x3', '\x1F', '\x5', '\x1F', '\x13F', '\n', '\x1F', '\x3', ' ', - '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x6', ' ', '\x145', '\n', ' ', '\r', - ' ', '\xE', ' ', '\x146', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', ' ', - '\x6', ' ', '\x14D', '\n', ' ', '\r', ' ', '\xE', ' ', '\x14E', '\x3', - ' ', '\x5', ' ', '\x152', '\n', ' ', '\x3', '!', '\x3', '!', '\x3', '\"', - '\x5', '\"', '\x157', '\n', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', - '\x3', '#', '\x5', '#', '\x15D', '\n', '#', '\x3', '#', '\x5', '#', '\x160', - '\n', '#', '\x3', '#', '\x3', '#', '\x3', '#', '\x3', '#', '\x5', '#', - '\x166', '\n', '#', '\x3', '#', '\x3', '#', '\x3', '$', '\x3', '$', '\x3', - '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', - '$', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', - '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '\'', '\x3', '\'', '\x3', - '\'', '\x3', '\'', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', ')', '\x3', - ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', '*', '\x3', - '*', '\x3', '*', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', - '+', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', - ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', - '-', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', - '.', '\x3', '.', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', - '/', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', - '\x30', '\x3', '\x30', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', - '\x31', '\x3', '\x31', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', - '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x33', '\x3', '\x33', '\x3', - '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', - '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', - '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x36', '\x3', - '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x37', '\x3', '\x37', '\x3', - '\x37', '\x3', '\x37', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', - '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', - '\x39', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ';', '\x3', ';', '\x3', - ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', + 'w', '\t', 'w', '\x4', 'x', '\t', 'x', '\x3', '\x2', '\x3', '\x2', '\x3', + '\x3', '\x3', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', + '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', + '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', + '\v', '\x3', '\v', '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', + '\x3', '\xE', '\x3', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\x10', + '\x3', '\x10', '\x3', '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', + '\x3', '\x13', '\x3', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x15', + '\x3', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', '\x3', '\x17', + '\x3', '\x18', '\x3', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', + '\x3', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x3', '\x1C', + '\x3', '\x1D', '\x6', '\x1D', '\x129', '\n', '\x1D', '\r', '\x1D', '\xE', + '\x1D', '\x12A', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1F', '\x3', '\x1F', + '\x3', '\x1F', '\x3', '\x1F', '\x6', '\x1F', '\x133', '\n', '\x1F', '\r', + '\x1F', '\xE', '\x1F', '\x134', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', + '\x3', '\x1F', '\x6', '\x1F', '\x13B', '\n', '\x1F', '\r', '\x1F', '\xE', + '\x1F', '\x13C', '\x3', '\x1F', '\x3', '\x1F', '\x5', '\x1F', '\x141', + '\n', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x6', ' ', + '\x147', '\n', ' ', '\r', ' ', '\xE', ' ', '\x148', '\x3', ' ', '\x3', + ' ', '\x3', ' ', '\x3', ' ', '\x6', ' ', '\x14F', '\n', ' ', '\r', ' ', + '\xE', ' ', '\x150', '\x3', ' ', '\x5', ' ', '\x154', '\n', ' ', '\x3', + '!', '\x3', '!', '\x3', '\"', '\x5', '\"', '\x159', '\n', '\"', '\x3', + '\"', '\x3', '\"', '\x3', '\"', '\x3', '#', '\x5', '#', '\x15F', '\n', + '#', '\x3', '#', '\x5', '#', '\x162', '\n', '#', '\x3', '#', '\x3', '#', + '\x3', '#', '\x3', '#', '\x5', '#', '\x168', '\n', '#', '\x3', '#', '\x3', + '#', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', + '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', + '%', '\x3', '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', + '&', '\x3', '&', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', + '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', ')', '\x3', ')', '\x3', + ')', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', + '*', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x3', + ',', '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', + '-', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', '\x3', + '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '/', '\x3', + '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '\x30', '\x3', '\x30', + '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x31', '\x3', '\x31', + '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x32', + '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x33', + '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', + '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', + '\x3', '\x34', '\x3', '\x34', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', + '\x3', '\x35', '\x3', '\x35', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', + '\x3', '\x36', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', + '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x39', + '\x3', '\x39', '\x3', '\x39', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', + ':', '\x3', ':', '\x3', ':', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', - '<', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', - '=', '\x3', '=', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', - '>', '\x3', '>', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', - '?', '\x3', '?', '\x3', '?', '\x3', '@', '\x3', '@', '\x3', '@', '\x3', - '@', '\x3', '@', '\x3', '@', '\x3', '@', '\x3', '\x41', '\x3', '\x41', - '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x42', - '\x3', '\x42', '\x3', '\x42', '\x3', '\x42', '\x3', '\x42', '\x3', '\x42', - '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', - '\x3', '\x44', '\x3', '\x44', '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', - '\x3', '\x45', '\x3', '\x46', '\x3', '\x46', '\x3', '\x46', '\x3', 'G', - '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', 'H', '\x3', 'H', '\x3', 'H', - '\x3', 'I', '\x3', 'I', '\x3', 'J', '\x3', 'J', '\x3', 'J', '\x3', 'K', - '\x3', 'K', '\x3', 'L', '\x3', 'L', '\x3', 'L', '\x3', 'M', '\x3', 'M', - '\x3', 'M', '\x3', 'M', '\x3', 'M', '\x3', 'N', '\x3', 'N', '\x3', 'O', - '\x3', 'O', '\x3', 'P', '\x3', 'P', '\x3', 'Q', '\x3', 'Q', '\x3', 'R', - '\x3', 'R', '\x3', 'S', '\x3', 'S', '\x3', 'T', '\x3', 'T', '\x3', 'U', - '\x3', 'U', '\x3', 'U', '\x3', 'V', '\x3', 'V', '\x3', 'V', '\x3', 'W', - '\x3', 'W', '\x3', 'W', '\x3', 'X', '\x3', 'X', '\x3', 'Y', '\x3', 'Y', - '\x3', 'Z', '\x3', 'Z', '\x3', 'Z', '\x3', '[', '\x3', '[', '\x3', '\\', - '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', '^', '\x3', '^', '\x3', '_', - '\x3', '_', '\x3', '`', '\x3', '`', '\x3', '\x61', '\x3', '\x61', '\x3', - '\x62', '\x3', '\x62', '\x3', '\x63', '\x3', '\x63', '\x3', '\x64', '\x3', - '\x64', '\x3', '\x65', '\x3', '\x65', '\x3', '\x65', '\x3', '\x65', '\x3', - '\x66', '\x6', '\x66', '\x26F', '\n', '\x66', '\r', '\x66', '\xE', '\x66', - '\x270', '\x3', '\x66', '\x3', '\x66', '\x3', '\x66', '\a', '\x66', '\x276', - '\n', '\x66', '\f', '\x66', '\xE', '\x66', '\x279', '\v', '\x66', '\x5', - '\x66', '\x27B', '\n', '\x66', '\x3', '\x66', '\x6', '\x66', '\x27E', - '\n', '\x66', '\r', '\x66', '\xE', '\x66', '\x27F', '\x3', '\x66', '\x3', - '\x66', '\a', '\x66', '\x284', '\n', '\x66', '\f', '\x66', '\xE', '\x66', - '\x287', '\v', '\x66', '\x3', '\x66', '\x3', '\x66', '\a', '\x66', '\x28B', - '\n', '\x66', '\f', '\x66', '\xE', '\x66', '\x28E', '\v', '\x66', '\x5', - '\x66', '\x290', '\n', '\x66', '\x3', 'g', '\x3', 'g', '\x3', 'g', '\x3', - 'h', '\x3', 'h', '\x3', 'i', '\x3', 'i', '\x3', 'j', '\x3', 'j', '\x3', - 'k', '\x3', 'k', '\x3', 'k', '\x5', 'k', '\x29E', '\n', 'k', '\x3', 'k', - '\a', 'k', '\x2A1', '\n', 'k', '\f', 'k', '\xE', 'k', '\x2A4', '\v', 'k', - '\x3', 'k', '\x3', 'k', '\x6', 'k', '\x2A8', '\n', 'k', '\r', 'k', '\xE', - 'k', '\x2A9', '\x3', 'l', '\x3', 'l', '\x5', 'l', '\x2AE', '\n', 'l', - '\x3', 'l', '\a', 'l', '\x2B1', '\n', 'l', '\f', 'l', '\xE', 'l', '\x2B4', - '\v', 'l', '\x3', 'l', '\x3', 'l', '\x6', 'l', '\x2B8', '\n', 'l', '\r', - 'l', '\xE', 'l', '\x2B9', '\x3', 'm', '\x3', 'm', '\x3', 'm', '\x3', 'm', - '\x3', 'm', '\x3', 'm', '\x3', 'm', '\x3', 'm', '\x3', 'm', '\a', 'm', - '\x2C5', '\n', 'm', '\f', 'm', '\xE', 'm', '\x2C8', '\v', 'm', '\x3', - 'm', '\x3', 'm', '\x5', 'm', '\x2CC', '\n', 'm', '\x3', 'm', '\x3', 'm', - '\x3', 'n', '\x3', 'n', '\a', 'n', '\x2D2', '\n', 'n', '\f', 'n', '\xE', - 'n', '\x2D5', '\v', 'n', '\x3', 'n', '\x3', 'n', '\x3', 'o', '\x3', 'o', - '\x3', 'o', '\a', 'o', '\x2DC', '\n', 'o', '\f', 'o', '\xE', 'o', '\x2DF', - '\v', 'o', '\x3', 'o', '\x3', 'o', '\x5', 'o', '\x2E3', '\n', 'o', '\x3', - 'o', '\x3', 'o', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', 'q', '\x3', - 'q', '\x3', 'r', '\x3', 'r', '\x3', 'r', '\x6', 'r', '\x2EF', '\n', 'r', - '\r', 'r', '\xE', 'r', '\x2F0', '\x3', 's', '\x3', 's', '\x3', 's', '\x3', - 't', '\x3', 't', '\x3', 't', '\x3', 'u', '\x3', 'u', '\x5', 'u', '\x2FB', - '\n', 'u', '\x3', 'v', '\x3', 'v', '\x3', 'w', '\x3', 'w', '\x5', '\x2A2', - '\x2B2', '\x2C6', '\x2', 'x', '\x3', '\x2', '\x5', '\x2', '\a', '\x2', - '\t', '\x2', '\v', '\x2', '\r', '\x2', '\xF', '\x2', '\x11', '\x2', '\x13', - '\x2', '\x15', '\x2', '\x17', '\x2', '\x19', '\x2', '\x1B', '\x2', '\x1D', - '\x2', '\x1F', '\x2', '!', '\x2', '#', '\x2', '%', '\x2', '\'', '\x2', - ')', '\x2', '+', '\x2', '-', '\x2', '/', '\x2', '\x31', '\x2', '\x33', - '\x2', '\x35', '\x2', '\x37', '\x2', '\x39', '\x2', ';', '\x2', '=', '\x3', - '?', '\x4', '\x41', '\x5', '\x43', '\x6', '\x45', '\a', 'G', '\b', 'I', - '\t', 'K', '\n', 'M', '\v', 'O', '\f', 'Q', '\r', 'S', '\xE', 'U', '\xF', - 'W', '\x10', 'Y', '\x11', '[', '\x12', ']', '\x13', '_', '\x14', '\x61', - '\x15', '\x63', '\x16', '\x65', '\x17', 'g', '\x18', 'i', '\x19', 'k', - '\x1A', 'm', '\x1B', 'o', '\x1C', 'q', '\x1D', 's', '\x1E', 'u', '\x1F', - 'w', ' ', 'y', '!', '{', '\"', '}', '#', '\x7F', '$', '\x81', '%', '\x83', - '&', '\x85', '\'', '\x87', '(', '\x89', ')', '\x8B', '*', '\x8D', '+', - '\x8F', ',', '\x91', '-', '\x93', '.', '\x95', '/', '\x97', '\x30', '\x99', - 'P', '\x9B', '\x31', '\x9D', '\x32', '\x9F', '\x33', '\xA1', '\x34', '\xA3', - '\x35', '\xA5', '\x36', '\xA7', '\x37', '\xA9', '\x38', '\xAB', '\x39', - '\xAD', ':', '\xAF', ';', '\xB1', '<', '\xB3', '=', '\xB5', '>', '\xB7', - '?', '\xB9', '@', '\xBB', '\x41', '\xBD', '\x42', '\xBF', '\x43', '\xC1', - '\x44', '\xC3', '\x45', '\xC5', '\x46', '\xC7', 'G', '\xC9', 'H', '\xCB', - 'I', '\xCD', 'J', '\xCF', '\x2', '\xD1', '\x2', '\xD3', '\x2', '\xD5', - 'K', '\xD7', 'L', '\xD9', 'M', '\xDB', 'N', '\xDD', 'O', '\xDF', '\x2', - '\xE1', '\x2', '\xE3', '\x2', '\xE5', '\x2', '\xE7', '\x2', '\xE9', '\x2', - '\xEB', '\x2', '\xED', '\x2', '\x3', '\x2', '&', '\x4', '\x2', '\x43', - '\x43', '\x63', '\x63', '\x4', '\x2', '\x44', '\x44', '\x64', '\x64', - '\x4', '\x2', '\x45', '\x45', '\x65', '\x65', '\x4', '\x2', '\x46', '\x46', - '\x66', '\x66', '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', '\x2', 'H', 'H', - 'h', 'h', '\x4', '\x2', 'I', 'I', 'i', 'i', '\x4', '\x2', 'J', 'J', 'j', - 'j', '\x4', '\x2', 'K', 'K', 'k', 'k', '\x4', '\x2', 'L', 'L', 'l', 'l', - '\x4', '\x2', 'M', 'M', 'm', 'm', '\x4', '\x2', 'N', 'N', 'n', 'n', '\x4', - '\x2', 'O', 'O', 'o', 'o', '\x4', '\x2', 'P', 'P', 'p', 'p', '\x4', '\x2', - 'Q', 'Q', 'q', 'q', '\x4', '\x2', 'R', 'R', 'r', 'r', '\x4', '\x2', 'S', - 'S', 's', 's', '\x4', '\x2', 'T', 'T', 't', 't', '\x4', '\x2', 'U', 'U', - 'u', 'u', '\x4', '\x2', 'V', 'V', 'v', 'v', '\x4', '\x2', 'W', 'W', 'w', - 'w', '\x4', '\x2', 'X', 'X', 'x', 'x', '\x4', '\x2', 'Y', 'Y', 'y', 'y', - '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x4', '\x2', '[', '[', '{', '{', '\x4', - '\x2', '\\', '\\', '|', '|', '\x3', '\x2', '\x32', ';', '\x5', '\x2', - '\x32', ';', '\x43', 'H', '\x63', 'h', '\x3', '\x2', '\x32', '\x33', '\x5', - '\x2', '\v', '\f', '\xE', '\xF', '\"', '\"', '\x3', '\x2', '#', '#', '\x4', - '\x2', '\f', '\f', '\xF', '\xF', '\x4', '\x2', '\v', '\v', '\"', '\"', - '\x6', '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', '\x63', '|', '\a', - '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x82', '\x1', - '\t', '\x2', '&', '&', '\x43', '\x46', 'H', '\\', '\x61', '\x61', '\x63', - '\x66', 'h', '|', '\x82', '\x1', '\x2', '\x2FB', '\x2', '=', '\x3', '\x2', - '\x2', '\x2', '\x2', '?', '\x3', '\x2', '\x2', '\x2', '\x2', '\x41', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x43', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x45', '\x3', '\x2', '\x2', '\x2', '\x2', 'G', '\x3', '\x2', '\x2', '\x2', - '\x2', 'I', '\x3', '\x2', '\x2', '\x2', '\x2', 'K', '\x3', '\x2', '\x2', - '\x2', '\x2', 'M', '\x3', '\x2', '\x2', '\x2', '\x2', 'O', '\x3', '\x2', - '\x2', '\x2', '\x2', 'Q', '\x3', '\x2', '\x2', '\x2', '\x2', 'S', '\x3', - '\x2', '\x2', '\x2', '\x2', 'U', '\x3', '\x2', '\x2', '\x2', '\x2', 'W', - '\x3', '\x2', '\x2', '\x2', '\x2', 'Y', '\x3', '\x2', '\x2', '\x2', '\x2', - '[', '\x3', '\x2', '\x2', '\x2', '\x2', ']', '\x3', '\x2', '\x2', '\x2', - '\x2', '_', '\x3', '\x2', '\x2', '\x2', '\x2', '\x61', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x63', '\x3', '\x2', '\x2', '\x2', '\x2', '\x65', '\x3', - '\x2', '\x2', '\x2', '\x2', 'g', '\x3', '\x2', '\x2', '\x2', '\x2', 'i', - '\x3', '\x2', '\x2', '\x2', '\x2', 'k', '\x3', '\x2', '\x2', '\x2', '\x2', - 'm', '\x3', '\x2', '\x2', '\x2', '\x2', 'o', '\x3', '\x2', '\x2', '\x2', - '\x2', 'q', '\x3', '\x2', '\x2', '\x2', '\x2', 's', '\x3', '\x2', '\x2', - '\x2', '\x2', 'u', '\x3', '\x2', '\x2', '\x2', '\x2', 'w', '\x3', '\x2', - '\x2', '\x2', '\x2', 'y', '\x3', '\x2', '\x2', '\x2', '\x2', '{', '\x3', - '\x2', '\x2', '\x2', '\x2', '}', '\x3', '\x2', '\x2', '\x2', '\x2', '\x7F', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x81', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x83', '\x3', '\x2', '\x2', '\x2', '\x2', '\x85', '\x3', '\x2', - '\x2', '\x2', '\x2', '\x87', '\x3', '\x2', '\x2', '\x2', '\x2', '\x89', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x8B', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x2', '\x8F', '\x3', '\x2', - '\x2', '\x2', '\x2', '\x91', '\x3', '\x2', '\x2', '\x2', '\x2', '\x93', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x95', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x97', '\x3', '\x2', '\x2', '\x2', '\x2', '\x99', '\x3', '\x2', - '\x2', '\x2', '\x2', '\x9B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x9D', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x9F', '\x3', '\x2', '\x2', '\x2', - '\x2', '\xA1', '\x3', '\x2', '\x2', '\x2', '\x2', '\xA3', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xA5', '\x3', '\x2', '\x2', '\x2', '\x2', '\xA7', - '\x3', '\x2', '\x2', '\x2', '\x2', '\xA9', '\x3', '\x2', '\x2', '\x2', - '\x2', '\xAB', '\x3', '\x2', '\x2', '\x2', '\x2', '\xAD', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xAF', '\x3', '\x2', '\x2', '\x2', '\x2', '\xB1', - '\x3', '\x2', '\x2', '\x2', '\x2', '\xB3', '\x3', '\x2', '\x2', '\x2', - '\x2', '\xB5', '\x3', '\x2', '\x2', '\x2', '\x2', '\xB7', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xB9', '\x3', '\x2', '\x2', '\x2', '\x2', '\xBB', - '\x3', '\x2', '\x2', '\x2', '\x2', '\xBD', '\x3', '\x2', '\x2', '\x2', - '\x2', '\xBF', '\x3', '\x2', '\x2', '\x2', '\x2', '\xC1', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xC3', '\x3', '\x2', '\x2', '\x2', '\x2', '\xC5', - '\x3', '\x2', '\x2', '\x2', '\x2', '\xC7', '\x3', '\x2', '\x2', '\x2', - '\x2', '\xC9', '\x3', '\x2', '\x2', '\x2', '\x2', '\xCB', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xCD', '\x3', '\x2', '\x2', '\x2', '\x2', '\xD5', - '\x3', '\x2', '\x2', '\x2', '\x2', '\xD7', '\x3', '\x2', '\x2', '\x2', - '\x2', '\xD9', '\x3', '\x2', '\x2', '\x2', '\x2', '\xDB', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xDD', '\x3', '\x2', '\x2', '\x2', '\x3', '\xEF', - '\x3', '\x2', '\x2', '\x2', '\x5', '\xF1', '\x3', '\x2', '\x2', '\x2', - '\a', '\xF3', '\x3', '\x2', '\x2', '\x2', '\t', '\xF5', '\x3', '\x2', - '\x2', '\x2', '\v', '\xF7', '\x3', '\x2', '\x2', '\x2', '\r', '\xF9', - '\x3', '\x2', '\x2', '\x2', '\xF', '\xFB', '\x3', '\x2', '\x2', '\x2', - '\x11', '\xFD', '\x3', '\x2', '\x2', '\x2', '\x13', '\xFF', '\x3', '\x2', - '\x2', '\x2', '\x15', '\x101', '\x3', '\x2', '\x2', '\x2', '\x17', '\x103', - '\x3', '\x2', '\x2', '\x2', '\x19', '\x105', '\x3', '\x2', '\x2', '\x2', - '\x1B', '\x107', '\x3', '\x2', '\x2', '\x2', '\x1D', '\x109', '\x3', '\x2', - '\x2', '\x2', '\x1F', '\x10B', '\x3', '\x2', '\x2', '\x2', '!', '\x10D', - '\x3', '\x2', '\x2', '\x2', '#', '\x10F', '\x3', '\x2', '\x2', '\x2', - '%', '\x111', '\x3', '\x2', '\x2', '\x2', '\'', '\x113', '\x3', '\x2', - '\x2', '\x2', ')', '\x115', '\x3', '\x2', '\x2', '\x2', '+', '\x117', - '\x3', '\x2', '\x2', '\x2', '-', '\x119', '\x3', '\x2', '\x2', '\x2', - '/', '\x11B', '\x3', '\x2', '\x2', '\x2', '\x31', '\x11D', '\x3', '\x2', - '\x2', '\x2', '\x33', '\x11F', '\x3', '\x2', '\x2', '\x2', '\x35', '\x121', - '\x3', '\x2', '\x2', '\x2', '\x37', '\x123', '\x3', '\x2', '\x2', '\x2', - '\x39', '\x126', '\x3', '\x2', '\x2', '\x2', ';', '\x12A', '\x3', '\x2', - '\x2', '\x2', '=', '\x13E', '\x3', '\x2', '\x2', '\x2', '?', '\x151', - '\x3', '\x2', '\x2', '\x2', '\x41', '\x153', '\x3', '\x2', '\x2', '\x2', - '\x43', '\x156', '\x3', '\x2', '\x2', '\x2', '\x45', '\x15F', '\x3', '\x2', - '\x2', '\x2', 'G', '\x169', '\x3', '\x2', '\x2', '\x2', 'I', '\x172', - '\x3', '\x2', '\x2', '\x2', 'K', '\x177', '\x3', '\x2', '\x2', '\x2', - 'M', '\x17B', '\x3', '\x2', '\x2', '\x2', 'O', '\x17F', '\x3', '\x2', - '\x2', '\x2', 'Q', '\x182', '\x3', '\x2', '\x2', '\x2', 'S', '\x188', - '\x3', '\x2', '\x2', '\x2', 'U', '\x18B', '\x3', '\x2', '\x2', '\x2', - 'W', '\x190', '\x3', '\x2', '\x2', '\x2', 'Y', '\x197', '\x3', '\x2', - '\x2', '\x2', '[', '\x19E', '\x3', '\x2', '\x2', '\x2', ']', '\x1A3', - '\x3', '\x2', '\x2', '\x2', '_', '\x1A8', '\x3', '\x2', '\x2', '\x2', - '\x61', '\x1AE', '\x3', '\x2', '\x2', '\x2', '\x63', '\x1B3', '\x3', '\x2', - '\x2', '\x2', '\x65', '\x1B9', '\x3', '\x2', '\x2', '\x2', 'g', '\x1C0', - '\x3', '\x2', '\x2', '\x2', 'i', '\x1C5', '\x3', '\x2', '\x2', '\x2', - 'k', '\x1C9', '\x3', '\x2', '\x2', '\x2', 'm', '\x1CD', '\x3', '\x2', - '\x2', '\x2', 'o', '\x1D1', '\x3', '\x2', '\x2', '\x2', 'q', '\x1D4', - '\x3', '\x2', '\x2', '\x2', 's', '\x1DA', '\x3', '\x2', '\x2', '\x2', - 'u', '\x1DD', '\x3', '\x2', '\x2', '\x2', 'w', '\x1E5', '\x3', '\x2', + '<', '\x3', '<', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\x3', '=', '\x3', '=', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', + '>', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', '?', '\x3', '?', '\x3', + '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '@', '\x3', '@', '\x3', + '@', '\x3', '@', '\x3', '@', '\x3', '@', '\x3', '@', '\x3', '\x41', '\x3', + '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', + '\x41', '\x3', '\x42', '\x3', '\x42', '\x3', '\x42', '\x3', '\x42', '\x3', + '\x42', '\x3', '\x42', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', + '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x44', '\x3', '\x44', '\x3', + '\x44', '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', '\x3', '\x45', '\x3', + '\x45', '\x3', '\x45', '\x3', '\x46', '\x3', '\x46', '\x3', 'G', '\x3', + 'G', '\x3', 'G', '\x3', 'H', '\x3', 'H', '\x3', 'H', '\x3', 'H', '\x3', + 'I', '\x3', 'I', '\x3', 'I', '\x3', 'J', '\x3', 'J', '\x3', 'K', '\x3', + 'K', '\x3', 'K', '\x3', 'L', '\x3', 'L', '\x3', 'M', '\x3', 'M', '\x3', + 'M', '\x3', 'N', '\x3', 'N', '\x3', 'N', '\x3', 'N', '\x3', 'N', '\x3', + 'O', '\x3', 'O', '\x3', 'P', '\x3', 'P', '\x3', 'Q', '\x3', 'Q', '\x3', + 'R', '\x3', 'R', '\x3', 'S', '\x3', 'S', '\x3', 'T', '\x3', 'T', '\x3', + 'U', '\x3', 'U', '\x3', 'V', '\x3', 'V', '\x3', 'V', '\x3', 'W', '\x3', + 'W', '\x3', 'W', '\x3', 'X', '\x3', 'X', '\x3', 'X', '\x3', 'Y', '\x3', + 'Y', '\x3', 'Z', '\x3', 'Z', '\x3', '[', '\x3', '[', '\x3', '[', '\x3', + '\\', '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', '^', '\x3', '^', '\x3', + '_', '\x3', '_', '\x3', '`', '\x3', '`', '\x3', '\x61', '\x3', '\x61', + '\x3', '\x62', '\x3', '\x62', '\x3', '\x63', '\x3', '\x63', '\x3', '\x64', + '\x3', '\x64', '\x3', '\x65', '\x3', '\x65', '\x3', '\x66', '\x3', '\x66', + '\x3', '\x66', '\x3', '\x66', '\x3', 'g', '\x6', 'g', '\x276', '\n', 'g', + '\r', 'g', '\xE', 'g', '\x277', '\x3', 'g', '\x3', 'g', '\x3', 'g', '\a', + 'g', '\x27D', '\n', 'g', '\f', 'g', '\xE', 'g', '\x280', '\v', 'g', '\x5', + 'g', '\x282', '\n', 'g', '\x3', 'g', '\x6', 'g', '\x285', '\n', 'g', '\r', + 'g', '\xE', 'g', '\x286', '\x3', 'g', '\x3', 'g', '\a', 'g', '\x28B', + '\n', 'g', '\f', 'g', '\xE', 'g', '\x28E', '\v', 'g', '\x3', 'g', '\x3', + 'g', '\a', 'g', '\x292', '\n', 'g', '\f', 'g', '\xE', 'g', '\x295', '\v', + 'g', '\x5', 'g', '\x297', '\n', 'g', '\x3', 'h', '\x3', 'h', '\x3', 'h', + '\x3', 'i', '\x3', 'i', '\x3', 'j', '\x3', 'j', '\x3', 'k', '\x3', 'k', + '\x3', 'l', '\x3', 'l', '\x3', 'l', '\x5', 'l', '\x2A5', '\n', 'l', '\x3', + 'l', '\a', 'l', '\x2A8', '\n', 'l', '\f', 'l', '\xE', 'l', '\x2AB', '\v', + 'l', '\x3', 'l', '\x3', 'l', '\x6', 'l', '\x2AF', '\n', 'l', '\r', 'l', + '\xE', 'l', '\x2B0', '\x3', 'm', '\x3', 'm', '\x5', 'm', '\x2B5', '\n', + 'm', '\x3', 'm', '\a', 'm', '\x2B8', '\n', 'm', '\f', 'm', '\xE', 'm', + '\x2BB', '\v', 'm', '\x3', 'm', '\x3', 'm', '\x6', 'm', '\x2BF', '\n', + 'm', '\r', 'm', '\xE', 'm', '\x2C0', '\x3', 'n', '\x3', 'n', '\x3', 'n', + '\x3', 'n', '\x3', 'n', '\x3', 'n', '\x3', 'n', '\x3', 'n', '\x3', 'n', + '\a', 'n', '\x2CC', '\n', 'n', '\f', 'n', '\xE', 'n', '\x2CF', '\v', 'n', + '\x3', 'n', '\x3', 'n', '\x5', 'n', '\x2D3', '\n', 'n', '\x3', 'n', '\x3', + 'n', '\x3', 'o', '\x3', 'o', '\a', 'o', '\x2D9', '\n', 'o', '\f', 'o', + '\xE', 'o', '\x2DC', '\v', 'o', '\x3', 'o', '\x3', 'o', '\x3', 'p', '\x3', + 'p', '\x3', 'p', '\a', 'p', '\x2E3', '\n', 'p', '\f', 'p', '\xE', 'p', + '\x2E6', '\v', 'p', '\x3', 'p', '\x3', 'p', '\x5', 'p', '\x2EA', '\n', + 'p', '\x3', 'p', '\x3', 'p', '\x3', 'q', '\x3', 'q', '\x3', 'q', '\x3', + 'r', '\x3', 'r', '\x3', 's', '\x3', 's', '\x3', 's', '\x6', 's', '\x2F6', + '\n', 's', '\r', 's', '\xE', 's', '\x2F7', '\x3', 't', '\x3', 't', '\x3', + 't', '\x3', 'u', '\x3', 'u', '\x3', 'u', '\x3', 'v', '\x3', 'v', '\x5', + 'v', '\x302', '\n', 'v', '\x3', 'w', '\x3', 'w', '\x3', 'x', '\x3', 'x', + '\x5', '\x2A9', '\x2B9', '\x2CD', '\x2', 'y', '\x3', '\x2', '\x5', '\x2', + '\a', '\x2', '\t', '\x2', '\v', '\x2', '\r', '\x2', '\xF', '\x2', '\x11', + '\x2', '\x13', '\x2', '\x15', '\x2', '\x17', '\x2', '\x19', '\x2', '\x1B', + '\x2', '\x1D', '\x2', '\x1F', '\x2', '!', '\x2', '#', '\x2', '%', '\x2', + '\'', '\x2', ')', '\x2', '+', '\x2', '-', '\x2', '/', '\x2', '\x31', '\x2', + '\x33', '\x2', '\x35', '\x2', '\x37', '\x2', '\x39', '\x2', ';', '\x2', + '=', '\x3', '?', '\x4', '\x41', '\x5', '\x43', '\x6', '\x45', '\a', 'G', + '\b', 'I', '\t', 'K', '\n', 'M', '\v', 'O', '\f', 'Q', '\r', 'S', '\xE', + 'U', '\xF', 'W', '\x10', 'Y', '\x11', '[', '\x12', ']', '\x13', '_', '\x14', + '\x61', '\x15', '\x63', '\x16', '\x65', '\x17', 'g', '\x18', 'i', '\x19', + 'k', '\x1A', 'm', '\x1B', 'o', '\x1C', 'q', '\x1D', 's', '\x1E', 'u', + '\x1F', 'w', ' ', 'y', '!', '{', '\"', '}', '#', '\x7F', '$', '\x81', + '%', '\x83', '&', '\x85', '\'', '\x87', '(', '\x89', ')', '\x8B', '*', + '\x8D', '+', '\x8F', ',', '\x91', '-', '\x93', '.', '\x95', '/', '\x97', + '\x30', '\x99', '\x31', '\x9B', 'Q', '\x9D', '\x32', '\x9F', '\x33', '\xA1', + '\x34', '\xA3', '\x35', '\xA5', '\x36', '\xA7', '\x37', '\xA9', '\x38', + '\xAB', '\x39', '\xAD', ':', '\xAF', ';', '\xB1', '<', '\xB3', '=', '\xB5', + '>', '\xB7', '?', '\xB9', '@', '\xBB', '\x41', '\xBD', '\x42', '\xBF', + '\x43', '\xC1', '\x44', '\xC3', '\x45', '\xC5', '\x46', '\xC7', 'G', '\xC9', + 'H', '\xCB', 'I', '\xCD', 'J', '\xCF', 'K', '\xD1', '\x2', '\xD3', '\x2', + '\xD5', '\x2', '\xD7', 'L', '\xD9', 'M', '\xDB', 'N', '\xDD', 'O', '\xDF', + 'P', '\xE1', '\x2', '\xE3', '\x2', '\xE5', '\x2', '\xE7', '\x2', '\xE9', + '\x2', '\xEB', '\x2', '\xED', '\x2', '\xEF', '\x2', '\x3', '\x2', '&', + '\x4', '\x2', '\x43', '\x43', '\x63', '\x63', '\x4', '\x2', '\x44', '\x44', + '\x64', '\x64', '\x4', '\x2', '\x45', '\x45', '\x65', '\x65', '\x4', '\x2', + '\x46', '\x46', '\x66', '\x66', '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', + '\x2', 'H', 'H', 'h', 'h', '\x4', '\x2', 'I', 'I', 'i', 'i', '\x4', '\x2', + 'J', 'J', 'j', 'j', '\x4', '\x2', 'K', 'K', 'k', 'k', '\x4', '\x2', 'L', + 'L', 'l', 'l', '\x4', '\x2', 'M', 'M', 'm', 'm', '\x4', '\x2', 'N', 'N', + 'n', 'n', '\x4', '\x2', 'O', 'O', 'o', 'o', '\x4', '\x2', 'P', 'P', 'p', + 'p', '\x4', '\x2', 'Q', 'Q', 'q', 'q', '\x4', '\x2', 'R', 'R', 'r', 'r', + '\x4', '\x2', 'S', 'S', 's', 's', '\x4', '\x2', 'T', 'T', 't', 't', '\x4', + '\x2', 'U', 'U', 'u', 'u', '\x4', '\x2', 'V', 'V', 'v', 'v', '\x4', '\x2', + 'W', 'W', 'w', 'w', '\x4', '\x2', 'X', 'X', 'x', 'x', '\x4', '\x2', 'Y', + 'Y', 'y', 'y', '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x4', '\x2', '[', '[', + '{', '{', '\x4', '\x2', '\\', '\\', '|', '|', '\x3', '\x2', '\x32', ';', + '\x5', '\x2', '\x32', ';', '\x43', 'H', '\x63', 'h', '\x3', '\x2', '\x32', + '\x33', '\x5', '\x2', '\v', '\f', '\xE', '\xF', '\"', '\"', '\x3', '\x2', + '#', '#', '\x4', '\x2', '\f', '\f', '\xF', '\xF', '\x4', '\x2', '\v', + '\v', '\"', '\"', '\x6', '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', + '\x63', '|', '\a', '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', '\x63', + '|', '\x82', '\x1', '\t', '\x2', '&', '&', '\x43', '\x46', 'H', '\\', + '\x61', '\x61', '\x63', '\x66', 'h', '|', '\x82', '\x1', '\x2', '\x302', + '\x2', '=', '\x3', '\x2', '\x2', '\x2', '\x2', '?', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x41', '\x3', '\x2', '\x2', '\x2', '\x2', '\x43', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x45', '\x3', '\x2', '\x2', '\x2', '\x2', + 'G', '\x3', '\x2', '\x2', '\x2', '\x2', 'I', '\x3', '\x2', '\x2', '\x2', + '\x2', 'K', '\x3', '\x2', '\x2', '\x2', '\x2', 'M', '\x3', '\x2', '\x2', + '\x2', '\x2', 'O', '\x3', '\x2', '\x2', '\x2', '\x2', 'Q', '\x3', '\x2', + '\x2', '\x2', '\x2', 'S', '\x3', '\x2', '\x2', '\x2', '\x2', 'U', '\x3', + '\x2', '\x2', '\x2', '\x2', 'W', '\x3', '\x2', '\x2', '\x2', '\x2', 'Y', + '\x3', '\x2', '\x2', '\x2', '\x2', '[', '\x3', '\x2', '\x2', '\x2', '\x2', + ']', '\x3', '\x2', '\x2', '\x2', '\x2', '_', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x61', '\x3', '\x2', '\x2', '\x2', '\x2', '\x63', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x65', '\x3', '\x2', '\x2', '\x2', '\x2', 'g', '\x3', + '\x2', '\x2', '\x2', '\x2', 'i', '\x3', '\x2', '\x2', '\x2', '\x2', 'k', + '\x3', '\x2', '\x2', '\x2', '\x2', 'm', '\x3', '\x2', '\x2', '\x2', '\x2', + 'o', '\x3', '\x2', '\x2', '\x2', '\x2', 'q', '\x3', '\x2', '\x2', '\x2', + '\x2', 's', '\x3', '\x2', '\x2', '\x2', '\x2', 'u', '\x3', '\x2', '\x2', + '\x2', '\x2', 'w', '\x3', '\x2', '\x2', '\x2', '\x2', 'y', '\x3', '\x2', + '\x2', '\x2', '\x2', '{', '\x3', '\x2', '\x2', '\x2', '\x2', '}', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x7F', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x81', '\x3', '\x2', '\x2', '\x2', '\x2', '\x83', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x85', '\x3', '\x2', '\x2', '\x2', '\x2', '\x87', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x89', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x8B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x8D', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x8F', '\x3', '\x2', '\x2', '\x2', '\x2', '\x91', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x93', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x95', '\x3', '\x2', '\x2', '\x2', '\x2', '\x97', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x99', '\x3', '\x2', '\x2', '\x2', '\x2', '\x9B', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x9D', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x9F', '\x3', '\x2', '\x2', '\x2', '\x2', '\xA1', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xA3', '\x3', '\x2', '\x2', '\x2', '\x2', '\xA5', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xA7', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xA9', '\x3', '\x2', '\x2', '\x2', '\x2', '\xAB', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xAD', '\x3', '\x2', '\x2', '\x2', '\x2', '\xAF', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xB1', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xB3', '\x3', '\x2', '\x2', '\x2', '\x2', '\xB5', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xB7', '\x3', '\x2', '\x2', '\x2', '\x2', '\xB9', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xBB', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xBD', '\x3', '\x2', '\x2', '\x2', '\x2', '\xBF', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xC1', '\x3', '\x2', '\x2', '\x2', '\x2', '\xC3', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xC5', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xC7', '\x3', '\x2', '\x2', '\x2', '\x2', '\xC9', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xCB', '\x3', '\x2', '\x2', '\x2', '\x2', '\xCD', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xCF', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xD7', '\x3', '\x2', '\x2', '\x2', '\x2', '\xD9', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xDB', '\x3', '\x2', '\x2', '\x2', '\x2', '\xDD', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xDF', '\x3', '\x2', '\x2', '\x2', '\x3', + '\xF1', '\x3', '\x2', '\x2', '\x2', '\x5', '\xF3', '\x3', '\x2', '\x2', + '\x2', '\a', '\xF5', '\x3', '\x2', '\x2', '\x2', '\t', '\xF7', '\x3', + '\x2', '\x2', '\x2', '\v', '\xF9', '\x3', '\x2', '\x2', '\x2', '\r', '\xFB', + '\x3', '\x2', '\x2', '\x2', '\xF', '\xFD', '\x3', '\x2', '\x2', '\x2', + '\x11', '\xFF', '\x3', '\x2', '\x2', '\x2', '\x13', '\x101', '\x3', '\x2', + '\x2', '\x2', '\x15', '\x103', '\x3', '\x2', '\x2', '\x2', '\x17', '\x105', + '\x3', '\x2', '\x2', '\x2', '\x19', '\x107', '\x3', '\x2', '\x2', '\x2', + '\x1B', '\x109', '\x3', '\x2', '\x2', '\x2', '\x1D', '\x10B', '\x3', '\x2', + '\x2', '\x2', '\x1F', '\x10D', '\x3', '\x2', '\x2', '\x2', '!', '\x10F', + '\x3', '\x2', '\x2', '\x2', '#', '\x111', '\x3', '\x2', '\x2', '\x2', + '%', '\x113', '\x3', '\x2', '\x2', '\x2', '\'', '\x115', '\x3', '\x2', + '\x2', '\x2', ')', '\x117', '\x3', '\x2', '\x2', '\x2', '+', '\x119', + '\x3', '\x2', '\x2', '\x2', '-', '\x11B', '\x3', '\x2', '\x2', '\x2', + '/', '\x11D', '\x3', '\x2', '\x2', '\x2', '\x31', '\x11F', '\x3', '\x2', + '\x2', '\x2', '\x33', '\x121', '\x3', '\x2', '\x2', '\x2', '\x35', '\x123', + '\x3', '\x2', '\x2', '\x2', '\x37', '\x125', '\x3', '\x2', '\x2', '\x2', + '\x39', '\x128', '\x3', '\x2', '\x2', '\x2', ';', '\x12C', '\x3', '\x2', + '\x2', '\x2', '=', '\x140', '\x3', '\x2', '\x2', '\x2', '?', '\x153', + '\x3', '\x2', '\x2', '\x2', '\x41', '\x155', '\x3', '\x2', '\x2', '\x2', + '\x43', '\x158', '\x3', '\x2', '\x2', '\x2', '\x45', '\x161', '\x3', '\x2', + '\x2', '\x2', 'G', '\x16B', '\x3', '\x2', '\x2', '\x2', 'I', '\x170', + '\x3', '\x2', '\x2', '\x2', 'K', '\x179', '\x3', '\x2', '\x2', '\x2', + 'M', '\x17E', '\x3', '\x2', '\x2', '\x2', 'O', '\x182', '\x3', '\x2', + '\x2', '\x2', 'Q', '\x186', '\x3', '\x2', '\x2', '\x2', 'S', '\x189', + '\x3', '\x2', '\x2', '\x2', 'U', '\x18F', '\x3', '\x2', '\x2', '\x2', + 'W', '\x192', '\x3', '\x2', '\x2', '\x2', 'Y', '\x197', '\x3', '\x2', + '\x2', '\x2', '[', '\x19E', '\x3', '\x2', '\x2', '\x2', ']', '\x1A5', + '\x3', '\x2', '\x2', '\x2', '_', '\x1AA', '\x3', '\x2', '\x2', '\x2', + '\x61', '\x1AF', '\x3', '\x2', '\x2', '\x2', '\x63', '\x1B5', '\x3', '\x2', + '\x2', '\x2', '\x65', '\x1BA', '\x3', '\x2', '\x2', '\x2', 'g', '\x1C0', + '\x3', '\x2', '\x2', '\x2', 'i', '\x1C7', '\x3', '\x2', '\x2', '\x2', + 'k', '\x1CC', '\x3', '\x2', '\x2', '\x2', 'm', '\x1D0', '\x3', '\x2', + '\x2', '\x2', 'o', '\x1D4', '\x3', '\x2', '\x2', '\x2', 'q', '\x1D8', + '\x3', '\x2', '\x2', '\x2', 's', '\x1DB', '\x3', '\x2', '\x2', '\x2', + 'u', '\x1E1', '\x3', '\x2', '\x2', '\x2', 'w', '\x1E4', '\x3', '\x2', '\x2', '\x2', 'y', '\x1EC', '\x3', '\x2', '\x2', '\x2', '{', '\x1F3', - '\x3', '\x2', '\x2', '\x2', '}', '\x1F9', '\x3', '\x2', '\x2', '\x2', + '\x3', '\x2', '\x2', '\x2', '}', '\x1FA', '\x3', '\x2', '\x2', '\x2', '\x7F', '\x200', '\x3', '\x2', '\x2', '\x2', '\x81', '\x207', '\x3', '\x2', - '\x2', '\x2', '\x83', '\x20D', '\x3', '\x2', '\x2', '\x2', '\x85', '\x213', - '\x3', '\x2', '\x2', '\x2', '\x87', '\x218', '\x3', '\x2', '\x2', '\x2', - '\x89', '\x21C', '\x3', '\x2', '\x2', '\x2', '\x8B', '\x21E', '\x3', '\x2', - '\x2', '\x2', '\x8D', '\x221', '\x3', '\x2', '\x2', '\x2', '\x8F', '\x225', - '\x3', '\x2', '\x2', '\x2', '\x91', '\x228', '\x3', '\x2', '\x2', '\x2', - '\x93', '\x22A', '\x3', '\x2', '\x2', '\x2', '\x95', '\x22D', '\x3', '\x2', - '\x2', '\x2', '\x97', '\x22F', '\x3', '\x2', '\x2', '\x2', '\x99', '\x232', - '\x3', '\x2', '\x2', '\x2', '\x9B', '\x237', '\x3', '\x2', '\x2', '\x2', - '\x9D', '\x239', '\x3', '\x2', '\x2', '\x2', '\x9F', '\x23B', '\x3', '\x2', - '\x2', '\x2', '\xA1', '\x23D', '\x3', '\x2', '\x2', '\x2', '\xA3', '\x23F', - '\x3', '\x2', '\x2', '\x2', '\xA5', '\x241', '\x3', '\x2', '\x2', '\x2', - '\xA7', '\x243', '\x3', '\x2', '\x2', '\x2', '\xA9', '\x245', '\x3', '\x2', - '\x2', '\x2', '\xAB', '\x248', '\x3', '\x2', '\x2', '\x2', '\xAD', '\x24B', - '\x3', '\x2', '\x2', '\x2', '\xAF', '\x24E', '\x3', '\x2', '\x2', '\x2', - '\xB1', '\x250', '\x3', '\x2', '\x2', '\x2', '\xB3', '\x252', '\x3', '\x2', - '\x2', '\x2', '\xB5', '\x255', '\x3', '\x2', '\x2', '\x2', '\xB7', '\x257', - '\x3', '\x2', '\x2', '\x2', '\xB9', '\x259', '\x3', '\x2', '\x2', '\x2', - '\xBB', '\x25B', '\x3', '\x2', '\x2', '\x2', '\xBD', '\x25D', '\x3', '\x2', - '\x2', '\x2', '\xBF', '\x25F', '\x3', '\x2', '\x2', '\x2', '\xC1', '\x261', - '\x3', '\x2', '\x2', '\x2', '\xC3', '\x263', '\x3', '\x2', '\x2', '\x2', - '\xC5', '\x265', '\x3', '\x2', '\x2', '\x2', '\xC7', '\x267', '\x3', '\x2', - '\x2', '\x2', '\xC9', '\x269', '\x3', '\x2', '\x2', '\x2', '\xCB', '\x28F', - '\x3', '\x2', '\x2', '\x2', '\xCD', '\x291', '\x3', '\x2', '\x2', '\x2', - '\xCF', '\x294', '\x3', '\x2', '\x2', '\x2', '\xD1', '\x296', '\x3', '\x2', - '\x2', '\x2', '\xD3', '\x298', '\x3', '\x2', '\x2', '\x2', '\xD5', '\x2A7', - '\x3', '\x2', '\x2', '\x2', '\xD7', '\x2B7', '\x3', '\x2', '\x2', '\x2', - '\xD9', '\x2CB', '\x3', '\x2', '\x2', '\x2', '\xDB', '\x2CF', '\x3', '\x2', - '\x2', '\x2', '\xDD', '\x2D8', '\x3', '\x2', '\x2', '\x2', '\xDF', '\x2E6', - '\x3', '\x2', '\x2', '\x2', '\xE1', '\x2E9', '\x3', '\x2', '\x2', '\x2', - '\xE3', '\x2EE', '\x3', '\x2', '\x2', '\x2', '\xE5', '\x2F2', '\x3', '\x2', - '\x2', '\x2', '\xE7', '\x2F5', '\x3', '\x2', '\x2', '\x2', '\xE9', '\x2FA', - '\x3', '\x2', '\x2', '\x2', '\xEB', '\x2FC', '\x3', '\x2', '\x2', '\x2', - '\xED', '\x2FE', '\x3', '\x2', '\x2', '\x2', '\xEF', '\xF0', '\t', '\x2', - '\x2', '\x2', '\xF0', '\x4', '\x3', '\x2', '\x2', '\x2', '\xF1', '\xF2', - '\t', '\x3', '\x2', '\x2', '\xF2', '\x6', '\x3', '\x2', '\x2', '\x2', - '\xF3', '\xF4', '\t', '\x4', '\x2', '\x2', '\xF4', '\b', '\x3', '\x2', - '\x2', '\x2', '\xF5', '\xF6', '\t', '\x5', '\x2', '\x2', '\xF6', '\n', - '\x3', '\x2', '\x2', '\x2', '\xF7', '\xF8', '\t', '\x6', '\x2', '\x2', - '\xF8', '\f', '\x3', '\x2', '\x2', '\x2', '\xF9', '\xFA', '\t', '\a', - '\x2', '\x2', '\xFA', '\xE', '\x3', '\x2', '\x2', '\x2', '\xFB', '\xFC', - '\t', '\b', '\x2', '\x2', '\xFC', '\x10', '\x3', '\x2', '\x2', '\x2', - '\xFD', '\xFE', '\t', '\t', '\x2', '\x2', '\xFE', '\x12', '\x3', '\x2', - '\x2', '\x2', '\xFF', '\x100', '\t', '\n', '\x2', '\x2', '\x100', '\x14', - '\x3', '\x2', '\x2', '\x2', '\x101', '\x102', '\t', '\v', '\x2', '\x2', - '\x102', '\x16', '\x3', '\x2', '\x2', '\x2', '\x103', '\x104', '\t', '\f', - '\x2', '\x2', '\x104', '\x18', '\x3', '\x2', '\x2', '\x2', '\x105', '\x106', - '\t', '\r', '\x2', '\x2', '\x106', '\x1A', '\x3', '\x2', '\x2', '\x2', - '\x107', '\x108', '\t', '\xE', '\x2', '\x2', '\x108', '\x1C', '\x3', '\x2', - '\x2', '\x2', '\x109', '\x10A', '\t', '\xF', '\x2', '\x2', '\x10A', '\x1E', - '\x3', '\x2', '\x2', '\x2', '\x10B', '\x10C', '\t', '\x10', '\x2', '\x2', - '\x10C', ' ', '\x3', '\x2', '\x2', '\x2', '\x10D', '\x10E', '\t', '\x11', - '\x2', '\x2', '\x10E', '\"', '\x3', '\x2', '\x2', '\x2', '\x10F', '\x110', - '\t', '\x12', '\x2', '\x2', '\x110', '$', '\x3', '\x2', '\x2', '\x2', - '\x111', '\x112', '\t', '\x13', '\x2', '\x2', '\x112', '&', '\x3', '\x2', - '\x2', '\x2', '\x113', '\x114', '\t', '\x14', '\x2', '\x2', '\x114', '(', - '\x3', '\x2', '\x2', '\x2', '\x115', '\x116', '\t', '\x15', '\x2', '\x2', - '\x116', '*', '\x3', '\x2', '\x2', '\x2', '\x117', '\x118', '\t', '\x16', - '\x2', '\x2', '\x118', ',', '\x3', '\x2', '\x2', '\x2', '\x119', '\x11A', - '\t', '\x17', '\x2', '\x2', '\x11A', '.', '\x3', '\x2', '\x2', '\x2', - '\x11B', '\x11C', '\t', '\x18', '\x2', '\x2', '\x11C', '\x30', '\x3', - '\x2', '\x2', '\x2', '\x11D', '\x11E', '\t', '\x19', '\x2', '\x2', '\x11E', - '\x32', '\x3', '\x2', '\x2', '\x2', '\x11F', '\x120', '\t', '\x1A', '\x2', - '\x2', '\x120', '\x34', '\x3', '\x2', '\x2', '\x2', '\x121', '\x122', - '\t', '\x1B', '\x2', '\x2', '\x122', '\x36', '\x3', '\x2', '\x2', '\x2', - '\x123', '\x124', '\t', '\x1C', '\x2', '\x2', '\x124', '\x38', '\x3', - '\x2', '\x2', '\x2', '\x125', '\x127', '\x5', '\x37', '\x1C', '\x2', '\x126', - '\x125', '\x3', '\x2', '\x2', '\x2', '\x127', '\x128', '\x3', '\x2', '\x2', - '\x2', '\x128', '\x126', '\x3', '\x2', '\x2', '\x2', '\x128', '\x129', - '\x3', '\x2', '\x2', '\x2', '\x129', ':', '\x3', '\x2', '\x2', '\x2', - '\x12A', '\x12B', '\t', '\x1D', '\x2', '\x2', '\x12B', '<', '\x3', '\x2', - '\x2', '\x2', '\x12C', '\x12D', '\a', '\x32', '\x2', '\x2', '\x12D', '\x12E', - '\a', 'z', '\x2', '\x2', '\x12E', '\x130', '\x3', '\x2', '\x2', '\x2', - '\x12F', '\x131', '\x5', ';', '\x1E', '\x2', '\x130', '\x12F', '\x3', - '\x2', '\x2', '\x2', '\x131', '\x132', '\x3', '\x2', '\x2', '\x2', '\x132', - '\x130', '\x3', '\x2', '\x2', '\x2', '\x132', '\x133', '\x3', '\x2', '\x2', - '\x2', '\x133', '\x13F', '\x3', '\x2', '\x2', '\x2', '\x134', '\x135', - '\a', 'z', '\x2', '\x2', '\x135', '\x136', '\a', ')', '\x2', '\x2', '\x136', - '\x138', '\x3', '\x2', '\x2', '\x2', '\x137', '\x139', '\x5', ';', '\x1E', - '\x2', '\x138', '\x137', '\x3', '\x2', '\x2', '\x2', '\x139', '\x13A', - '\x3', '\x2', '\x2', '\x2', '\x13A', '\x138', '\x3', '\x2', '\x2', '\x2', - '\x13A', '\x13B', '\x3', '\x2', '\x2', '\x2', '\x13B', '\x13C', '\x3', - '\x2', '\x2', '\x2', '\x13C', '\x13D', '\a', ')', '\x2', '\x2', '\x13D', - '\x13F', '\x3', '\x2', '\x2', '\x2', '\x13E', '\x12C', '\x3', '\x2', '\x2', - '\x2', '\x13E', '\x134', '\x3', '\x2', '\x2', '\x2', '\x13F', '>', '\x3', - '\x2', '\x2', '\x2', '\x140', '\x141', '\a', '\x32', '\x2', '\x2', '\x141', - '\x142', '\a', '\x64', '\x2', '\x2', '\x142', '\x144', '\x3', '\x2', '\x2', - '\x2', '\x143', '\x145', '\t', '\x1E', '\x2', '\x2', '\x144', '\x143', - '\x3', '\x2', '\x2', '\x2', '\x145', '\x146', '\x3', '\x2', '\x2', '\x2', - '\x146', '\x144', '\x3', '\x2', '\x2', '\x2', '\x146', '\x147', '\x3', - '\x2', '\x2', '\x2', '\x147', '\x152', '\x3', '\x2', '\x2', '\x2', '\x148', - '\x149', '\a', '\x64', '\x2', '\x2', '\x149', '\x14A', '\a', ')', '\x2', - '\x2', '\x14A', '\x14C', '\x3', '\x2', '\x2', '\x2', '\x14B', '\x14D', - '\t', '\x1E', '\x2', '\x2', '\x14C', '\x14B', '\x3', '\x2', '\x2', '\x2', - '\x14D', '\x14E', '\x3', '\x2', '\x2', '\x2', '\x14E', '\x14C', '\x3', - '\x2', '\x2', '\x2', '\x14E', '\x14F', '\x3', '\x2', '\x2', '\x2', '\x14F', - '\x150', '\x3', '\x2', '\x2', '\x2', '\x150', '\x152', '\a', ')', '\x2', - '\x2', '\x151', '\x140', '\x3', '\x2', '\x2', '\x2', '\x151', '\x148', - '\x3', '\x2', '\x2', '\x2', '\x152', '@', '\x3', '\x2', '\x2', '\x2', - '\x153', '\x154', '\x5', '\x39', '\x1D', '\x2', '\x154', '\x42', '\x3', - '\x2', '\x2', '\x2', '\x155', '\x157', '\x5', '\x39', '\x1D', '\x2', '\x156', - '\x155', '\x3', '\x2', '\x2', '\x2', '\x156', '\x157', '\x3', '\x2', '\x2', - '\x2', '\x157', '\x158', '\x3', '\x2', '\x2', '\x2', '\x158', '\x159', - '\x5', '\xB7', '\\', '\x2', '\x159', '\x15A', '\x5', '\x39', '\x1D', '\x2', - '\x15A', '\x44', '\x3', '\x2', '\x2', '\x2', '\x15B', '\x15D', '\x5', - '\x39', '\x1D', '\x2', '\x15C', '\x15B', '\x3', '\x2', '\x2', '\x2', '\x15C', - '\x15D', '\x3', '\x2', '\x2', '\x2', '\x15D', '\x15E', '\x3', '\x2', '\x2', - '\x2', '\x15E', '\x160', '\x5', '\xB7', '\\', '\x2', '\x15F', '\x15C', - '\x3', '\x2', '\x2', '\x2', '\x15F', '\x160', '\x3', '\x2', '\x2', '\x2', - '\x160', '\x161', '\x3', '\x2', '\x2', '\x2', '\x161', '\x162', '\x5', - '\x39', '\x1D', '\x2', '\x162', '\x165', '\t', '\x6', '\x2', '\x2', '\x163', - '\x166', '\x5', '\x9D', 'O', '\x2', '\x164', '\x166', '\x5', '\x9B', 'N', - '\x2', '\x165', '\x163', '\x3', '\x2', '\x2', '\x2', '\x165', '\x164', - '\x3', '\x2', '\x2', '\x2', '\x165', '\x166', '\x3', '\x2', '\x2', '\x2', - '\x166', '\x167', '\x3', '\x2', '\x2', '\x2', '\x167', '\x168', '\x5', - '\x39', '\x1D', '\x2', '\x168', '\x46', '\x3', '\x2', '\x2', '\x2', '\x169', - '\x16A', '\x5', '\v', '\x6', '\x2', '\x16A', '\x16B', '\x5', '\x31', '\x19', - '\x2', '\x16B', '\x16C', '\x5', '\v', '\x6', '\x2', '\x16C', '\x16D', - '\x5', '\a', '\x4', '\x2', '\x16D', '\x16E', '\x5', '\r', '\a', '\x2', - '\x16E', '\x16F', '\x5', '\x13', '\n', '\x2', '\x16F', '\x170', '\x5', - '\x19', '\r', '\x2', '\x170', '\x171', '\x5', '\v', '\x6', '\x2', '\x171', - 'H', '\x3', '\x2', '\x2', '\x2', '\x172', '\x173', '\x5', '#', '\x12', - '\x2', '\x173', '\x174', '\x5', '+', '\x16', '\x2', '\x174', '\x175', - '\x5', '\x13', '\n', '\x2', '\x175', '\x176', '\x5', ')', '\x15', '\x2', - '\x176', 'J', '\x3', '\x2', '\x2', '\x2', '\x177', '\x178', '\x5', '\x3', - '\x2', '\x2', '\x178', '\x179', '\x5', '\x1D', '\xF', '\x2', '\x179', - '\x17A', '\x5', '\t', '\x5', '\x2', '\x17A', 'L', '\x3', '\x2', '\x2', - '\x2', '\x17B', '\x17C', '\x5', '\x3', '\x2', '\x2', '\x17C', '\x17D', - '\x5', '\'', '\x14', '\x2', '\x17D', '\x17E', '\x5', '\a', '\x4', '\x2', - '\x17E', 'N', '\x3', '\x2', '\x2', '\x2', '\x17F', '\x180', '\x5', '\x3', - '\x2', '\x2', '\x180', '\x181', '\x5', '\'', '\x14', '\x2', '\x181', 'P', - '\x3', '\x2', '\x2', '\x2', '\x182', '\x183', '\x5', '\x5', '\x3', '\x2', - '\x183', '\x184', '\x5', '\v', '\x6', '\x2', '\x184', '\x185', '\x5', - '\xF', '\b', '\x2', '\x185', '\x186', '\x5', '\x13', '\n', '\x2', '\x186', - '\x187', '\x5', '\x1D', '\xF', '\x2', '\x187', 'R', '\x3', '\x2', '\x2', - '\x2', '\x188', '\x189', '\x5', '\x5', '\x3', '\x2', '\x189', '\x18A', - '\x5', '\x33', '\x1A', '\x2', '\x18A', 'T', '\x3', '\x2', '\x2', '\x2', - '\x18B', '\x18C', '\x5', '\a', '\x4', '\x2', '\x18C', '\x18D', '\x5', - '\x11', '\t', '\x2', '\x18D', '\x18E', '\x5', '\x3', '\x2', '\x2', '\x18E', - '\x18F', '\x5', '%', '\x13', '\x2', '\x18F', 'V', '\x3', '\x2', '\x2', - '\x2', '\x190', '\x191', '\x5', '\a', '\x4', '\x2', '\x191', '\x192', - '\x5', '%', '\x13', '\x2', '\x192', '\x193', '\x5', '\v', '\x6', '\x2', - '\x193', '\x194', '\x5', '\x3', '\x2', '\x2', '\x194', '\x195', '\x5', - ')', '\x15', '\x2', '\x195', '\x196', '\x5', '\v', '\x6', '\x2', '\x196', - 'X', '\x3', '\x2', '\x2', '\x2', '\x197', '\x198', '\x5', '\t', '\x5', - '\x2', '\x198', '\x199', '\x5', '\v', '\x6', '\x2', '\x199', '\x19A', - '\x5', '\x19', '\r', '\x2', '\x19A', '\x19B', '\x5', '\v', '\x6', '\x2', - '\x19B', '\x19C', '\x5', ')', '\x15', '\x2', '\x19C', '\x19D', '\x5', - '\v', '\x6', '\x2', '\x19D', 'Z', '\x3', '\x2', '\x2', '\x2', '\x19E', - '\x19F', '\x5', '\t', '\x5', '\x2', '\x19F', '\x1A0', '\x5', '\v', '\x6', - '\x2', '\x1A0', '\x1A1', '\x5', '\'', '\x14', '\x2', '\x1A1', '\x1A2', - '\x5', '\a', '\x4', '\x2', '\x1A2', '\\', '\x3', '\x2', '\x2', '\x2', - '\x1A3', '\x1A4', '\x5', '\t', '\x5', '\x2', '\x1A4', '\x1A5', '\x5', - '%', '\x13', '\x2', '\x1A5', '\x1A6', '\x5', '\x1F', '\x10', '\x2', '\x1A6', - '\x1A7', '\x5', '!', '\x11', '\x2', '\x1A7', '^', '\x3', '\x2', '\x2', - '\x2', '\x1A8', '\x1A9', '\x5', '\r', '\a', '\x2', '\x1A9', '\x1AA', '\x5', - '\x19', '\r', '\x2', '\x1AA', '\x1AB', '\x5', '\x1F', '\x10', '\x2', '\x1AB', - '\x1AC', '\x5', '\x3', '\x2', '\x2', '\x1AC', '\x1AD', '\x5', ')', '\x15', - '\x2', '\x1AD', '`', '\x3', '\x2', '\x2', '\x2', '\x1AE', '\x1AF', '\x5', - '\r', '\a', '\x2', '\x1AF', '\x1B0', '\x5', '%', '\x13', '\x2', '\x1B0', - '\x1B1', '\x5', '\x1F', '\x10', '\x2', '\x1B1', '\x1B2', '\x5', '\x1B', - '\xE', '\x2', '\x1B2', '\x62', '\x3', '\x2', '\x2', '\x2', '\x1B3', '\x1B4', - '\x5', '\x13', '\n', '\x2', '\x1B4', '\x1B5', '\x5', '\x1D', '\xF', '\x2', - '\x1B5', '\x1B6', '\x5', '\t', '\x5', '\x2', '\x1B6', '\x1B7', '\x5', - '\v', '\x6', '\x2', '\x1B7', '\x1B8', '\x5', '\x31', '\x19', '\x2', '\x1B8', - '\x64', '\x3', '\x2', '\x2', '\x2', '\x1B9', '\x1BA', '\x5', '\x13', '\n', - '\x2', '\x1BA', '\x1BB', '\x5', '\x1D', '\xF', '\x2', '\x1BB', '\x1BC', - '\x5', '\'', '\x14', '\x2', '\x1BC', '\x1BD', '\x5', '\v', '\x6', '\x2', - '\x1BD', '\x1BE', '\x5', '%', '\x13', '\x2', '\x1BE', '\x1BF', '\x5', - ')', '\x15', '\x2', '\x1BF', '\x66', '\x3', '\x2', '\x2', '\x2', '\x1C0', - '\x1C1', '\x5', '\x13', '\n', '\x2', '\x1C1', '\x1C2', '\x5', '\x1D', - '\xF', '\x2', '\x1C2', '\x1C3', '\x5', ')', '\x15', '\x2', '\x1C3', '\x1C4', - '\x5', '\x1F', '\x10', '\x2', '\x1C4', 'h', '\x3', '\x2', '\x2', '\x2', - '\x1C5', '\x1C6', '\x5', '\x13', '\n', '\x2', '\x1C6', '\x1C7', '\x5', - '\x1D', '\xF', '\x2', '\x1C7', '\x1C8', '\x5', ')', '\x15', '\x2', '\x1C8', - 'j', '\x3', '\x2', '\x2', '\x2', '\x1C9', '\x1CA', '\x5', '\x17', '\f', - '\x2', '\x1CA', '\x1CB', '\x5', '\v', '\x6', '\x2', '\x1CB', '\x1CC', - '\x5', '\x33', '\x1A', '\x2', '\x1CC', 'l', '\x3', '\x2', '\x2', '\x2', - '\x1CD', '\x1CE', '\x5', '\x1D', '\xF', '\x2', '\x1CE', '\x1CF', '\x5', - '\x1F', '\x10', '\x2', '\x1CF', '\x1D0', '\x5', ')', '\x15', '\x2', '\x1D0', - 'n', '\x3', '\x2', '\x2', '\x2', '\x1D1', '\x1D2', '\x5', '\x1F', '\x10', - '\x2', '\x1D2', '\x1D3', '\x5', '\x1D', '\xF', '\x2', '\x1D3', 'p', '\x3', - '\x2', '\x2', '\x2', '\x1D4', '\x1D5', '\x5', '\x1F', '\x10', '\x2', '\x1D5', - '\x1D6', '\x5', '%', '\x13', '\x2', '\x1D6', '\x1D7', '\x5', '\t', '\x5', - '\x2', '\x1D7', '\x1D8', '\x5', '\v', '\x6', '\x2', '\x1D8', '\x1D9', - '\x5', '%', '\x13', '\x2', '\x1D9', 'r', '\x3', '\x2', '\x2', '\x2', '\x1DA', - '\x1DB', '\x5', '\x1F', '\x10', '\x2', '\x1DB', '\x1DC', '\x5', '%', '\x13', - '\x2', '\x1DC', 't', '\x3', '\x2', '\x2', '\x2', '\x1DD', '\x1DE', '\x5', - '!', '\x11', '\x2', '\x1DE', '\x1DF', '\x5', '%', '\x13', '\x2', '\x1DF', - '\x1E0', '\x5', '\x13', '\n', '\x2', '\x1E0', '\x1E1', '\x5', '\x1B', - '\xE', '\x2', '\x1E1', '\x1E2', '\x5', '\x3', '\x2', '\x2', '\x1E2', '\x1E3', - '\x5', '%', '\x13', '\x2', '\x1E3', '\x1E4', '\x5', '\x33', '\x1A', '\x2', - '\x1E4', 'v', '\x3', '\x2', '\x2', '\x2', '\x1E5', '\x1E6', '\x5', '\'', - '\x14', '\x2', '\x1E6', '\x1E7', '\x5', '\v', '\x6', '\x2', '\x1E7', '\x1E8', - '\x5', '\x19', '\r', '\x2', '\x1E8', '\x1E9', '\x5', '\v', '\x6', '\x2', - '\x1E9', '\x1EA', '\x5', '\a', '\x4', '\x2', '\x1EA', '\x1EB', '\x5', - ')', '\x15', '\x2', '\x1EB', 'x', '\x3', '\x2', '\x2', '\x2', '\x1EC', - '\x1ED', '\x5', ')', '\x15', '\x2', '\x1ED', '\x1EE', '\x5', '\x3', '\x2', - '\x2', '\x1EE', '\x1EF', '\x5', '\x5', '\x3', '\x2', '\x1EF', '\x1F0', - '\x5', '\x19', '\r', '\x2', '\x1F0', '\x1F1', '\x5', '\v', '\x6', '\x2', - '\x1F1', '\x1F2', '\x5', '\'', '\x14', '\x2', '\x1F2', 'z', '\x3', '\x2', - '\x2', '\x2', '\x1F3', '\x1F4', '\x5', ')', '\x15', '\x2', '\x1F4', '\x1F5', - '\x5', '\x3', '\x2', '\x2', '\x1F5', '\x1F6', '\x5', '\x5', '\x3', '\x2', - '\x1F6', '\x1F7', '\x5', '\x19', '\r', '\x2', '\x1F7', '\x1F8', '\x5', - '\v', '\x6', '\x2', '\x1F8', '|', '\x3', '\x2', '\x2', '\x2', '\x1F9', - '\x1FA', '\x5', '+', '\x16', '\x2', '\x1FA', '\x1FB', '\x5', '\x1D', '\xF', - '\x2', '\x1FB', '\x1FC', '\x5', '\x13', '\n', '\x2', '\x1FC', '\x1FD', - '\x5', '#', '\x12', '\x2', '\x1FD', '\x1FE', '\x5', '+', '\x16', '\x2', - '\x1FE', '\x1FF', '\x5', '\v', '\x6', '\x2', '\x1FF', '~', '\x3', '\x2', - '\x2', '\x2', '\x200', '\x201', '\x5', '-', '\x17', '\x2', '\x201', '\x202', - '\x5', '\x3', '\x2', '\x2', '\x202', '\x203', '\x5', '\x19', '\r', '\x2', - '\x203', '\x204', '\x5', '+', '\x16', '\x2', '\x204', '\x205', '\x5', - '\v', '\x6', '\x2', '\x205', '\x206', '\x5', '\'', '\x14', '\x2', '\x206', - '\x80', '\x3', '\x2', '\x2', '\x2', '\x207', '\x208', '\x5', '-', '\x17', - '\x2', '\x208', '\x209', '\x5', '\x3', '\x2', '\x2', '\x209', '\x20A', - '\x5', '\x19', '\r', '\x2', '\x20A', '\x20B', '\x5', '+', '\x16', '\x2', - '\x20B', '\x20C', '\x5', '\v', '\x6', '\x2', '\x20C', '\x82', '\x3', '\x2', - '\x2', '\x2', '\x20D', '\x20E', '\x5', '/', '\x18', '\x2', '\x20E', '\x20F', - '\x5', '\x11', '\t', '\x2', '\x20F', '\x210', '\x5', '\v', '\x6', '\x2', - '\x210', '\x211', '\x5', '%', '\x13', '\x2', '\x211', '\x212', '\x5', - '\v', '\x6', '\x2', '\x212', '\x84', '\x3', '\x2', '\x2', '\x2', '\x213', - '\x214', '\x5', '/', '\x18', '\x2', '\x214', '\x215', '\x5', '\x1F', '\x10', - '\x2', '\x215', '\x216', '\x5', '%', '\x13', '\x2', '\x216', '\x217', - '\x5', '\x17', '\f', '\x2', '\x217', '\x86', '\x3', '\x2', '\x2', '\x2', - '\x218', '\x219', '\x5', '\x31', '\x19', '\x2', '\x219', '\x21A', '\x5', - '\x1F', '\x10', '\x2', '\x21A', '\x21B', '\x5', '%', '\x13', '\x2', '\x21B', - '\x88', '\x3', '\x2', '\x2', '\x2', '\x21C', '\x21D', '\a', '?', '\x2', - '\x2', '\x21D', '\x8A', '\x3', '\x2', '\x2', '\x2', '\x21E', '\x21F', - '\a', '<', '\x2', '\x2', '\x21F', '\x220', '\a', '?', '\x2', '\x2', '\x220', - '\x8C', '\x3', '\x2', '\x2', '\x2', '\x221', '\x222', '\a', '>', '\x2', - '\x2', '\x222', '\x223', '\a', '?', '\x2', '\x2', '\x223', '\x224', '\a', - '@', '\x2', '\x2', '\x224', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x225', - '\x226', '\a', '@', '\x2', '\x2', '\x226', '\x227', '\a', '?', '\x2', - '\x2', '\x227', '\x90', '\x3', '\x2', '\x2', '\x2', '\x228', '\x229', - '\a', '@', '\x2', '\x2', '\x229', '\x92', '\x3', '\x2', '\x2', '\x2', - '\x22A', '\x22B', '\a', '>', '\x2', '\x2', '\x22B', '\x22C', '\a', '?', - '\x2', '\x2', '\x22C', '\x94', '\x3', '\x2', '\x2', '\x2', '\x22D', '\x22E', - '\a', '>', '\x2', '\x2', '\x22E', '\x96', '\x3', '\x2', '\x2', '\x2', - '\x22F', '\x230', '\a', '#', '\x2', '\x2', '\x230', '\x231', '\a', '?', - '\x2', '\x2', '\x231', '\x98', '\x3', '\x2', '\x2', '\x2', '\x232', '\x233', - '\a', '>', '\x2', '\x2', '\x233', '\x234', '\a', '@', '\x2', '\x2', '\x234', - '\x235', '\x3', '\x2', '\x2', '\x2', '\x235', '\x236', '\b', 'M', '\x2', - '\x2', '\x236', '\x9A', '\x3', '\x2', '\x2', '\x2', '\x237', '\x238', - '\a', '-', '\x2', '\x2', '\x238', '\x9C', '\x3', '\x2', '\x2', '\x2', - '\x239', '\x23A', '\a', '/', '\x2', '\x2', '\x23A', '\x9E', '\x3', '\x2', - '\x2', '\x2', '\x23B', '\x23C', '\a', ',', '\x2', '\x2', '\x23C', '\xA0', - '\x3', '\x2', '\x2', '\x2', '\x23D', '\x23E', '\a', '\x31', '\x2', '\x2', - '\x23E', '\xA2', '\x3', '\x2', '\x2', '\x2', '\x23F', '\x240', '\a', '\'', - '\x2', '\x2', '\x240', '\xA4', '\x3', '\x2', '\x2', '\x2', '\x241', '\x242', - '\a', '#', '\x2', '\x2', '\x242', '\xA6', '\x3', '\x2', '\x2', '\x2', - '\x243', '\x244', '\a', '\x80', '\x2', '\x2', '\x244', '\xA8', '\x3', - '\x2', '\x2', '\x2', '\x245', '\x246', '\a', '>', '\x2', '\x2', '\x246', - '\x247', '\a', '>', '\x2', '\x2', '\x247', '\xAA', '\x3', '\x2', '\x2', - '\x2', '\x248', '\x249', '\a', '@', '\x2', '\x2', '\x249', '\x24A', '\a', - '@', '\x2', '\x2', '\x24A', '\xAC', '\x3', '\x2', '\x2', '\x2', '\x24B', - '\x24C', '\a', '(', '\x2', '\x2', '\x24C', '\x24D', '\a', '(', '\x2', - '\x2', '\x24D', '\xAE', '\x3', '\x2', '\x2', '\x2', '\x24E', '\x24F', - '\a', '(', '\x2', '\x2', '\x24F', '\xB0', '\x3', '\x2', '\x2', '\x2', - '\x250', '\x251', '\a', '`', '\x2', '\x2', '\x251', '\xB2', '\x3', '\x2', - '\x2', '\x2', '\x252', '\x253', '\a', '~', '\x2', '\x2', '\x253', '\x254', - '\a', '~', '\x2', '\x2', '\x254', '\xB4', '\x3', '\x2', '\x2', '\x2', - '\x255', '\x256', '\a', '~', '\x2', '\x2', '\x256', '\xB6', '\x3', '\x2', - '\x2', '\x2', '\x257', '\x258', '\a', '\x30', '\x2', '\x2', '\x258', '\xB8', - '\x3', '\x2', '\x2', '\x2', '\x259', '\x25A', '\a', '.', '\x2', '\x2', - '\x25A', '\xBA', '\x3', '\x2', '\x2', '\x2', '\x25B', '\x25C', '\a', '=', - '\x2', '\x2', '\x25C', '\xBC', '\x3', '\x2', '\x2', '\x2', '\x25D', '\x25E', - '\a', '<', '\x2', '\x2', '\x25E', '\xBE', '\x3', '\x2', '\x2', '\x2', - '\x25F', '\x260', '\a', '*', '\x2', '\x2', '\x260', '\xC0', '\x3', '\x2', - '\x2', '\x2', '\x261', '\x262', '\a', '+', '\x2', '\x2', '\x262', '\xC2', - '\x3', '\x2', '\x2', '\x2', '\x263', '\x264', '\a', '}', '\x2', '\x2', - '\x264', '\xC4', '\x3', '\x2', '\x2', '\x2', '\x265', '\x266', '\a', '\x7F', - '\x2', '\x2', '\x266', '\xC6', '\x3', '\x2', '\x2', '\x2', '\x267', '\x268', - '\a', '\x61', '\x2', '\x2', '\x268', '\xC8', '\x3', '\x2', '\x2', '\x2', - '\x269', '\x26A', '\t', '\x1F', '\x2', '\x2', '\x26A', '\x26B', '\x3', - '\x2', '\x2', '\x2', '\x26B', '\x26C', '\b', '\x65', '\x3', '\x2', '\x26C', - '\xCA', '\x3', '\x2', '\x2', '\x2', '\x26D', '\x26F', '\x5', '\x39', '\x1D', - '\x2', '\x26E', '\x26D', '\x3', '\x2', '\x2', '\x2', '\x26F', '\x270', - '\x3', '\x2', '\x2', '\x2', '\x270', '\x26E', '\x3', '\x2', '\x2', '\x2', - '\x270', '\x271', '\x3', '\x2', '\x2', '\x2', '\x271', '\x272', '\x3', - '\x2', '\x2', '\x2', '\x272', '\x27A', '\t', '\x6', '\x2', '\x2', '\x273', - '\x277', '\x5', '\xEB', 'v', '\x2', '\x274', '\x276', '\x5', '\xE9', 'u', - '\x2', '\x275', '\x274', '\x3', '\x2', '\x2', '\x2', '\x276', '\x279', + '\x2', '\x2', '\x83', '\x20E', '\x3', '\x2', '\x2', '\x2', '\x85', '\x214', + '\x3', '\x2', '\x2', '\x2', '\x87', '\x21A', '\x3', '\x2', '\x2', '\x2', + '\x89', '\x21F', '\x3', '\x2', '\x2', '\x2', '\x8B', '\x223', '\x3', '\x2', + '\x2', '\x2', '\x8D', '\x225', '\x3', '\x2', '\x2', '\x2', '\x8F', '\x228', + '\x3', '\x2', '\x2', '\x2', '\x91', '\x22C', '\x3', '\x2', '\x2', '\x2', + '\x93', '\x22F', '\x3', '\x2', '\x2', '\x2', '\x95', '\x231', '\x3', '\x2', + '\x2', '\x2', '\x97', '\x234', '\x3', '\x2', '\x2', '\x2', '\x99', '\x236', + '\x3', '\x2', '\x2', '\x2', '\x9B', '\x239', '\x3', '\x2', '\x2', '\x2', + '\x9D', '\x23E', '\x3', '\x2', '\x2', '\x2', '\x9F', '\x240', '\x3', '\x2', + '\x2', '\x2', '\xA1', '\x242', '\x3', '\x2', '\x2', '\x2', '\xA3', '\x244', + '\x3', '\x2', '\x2', '\x2', '\xA5', '\x246', '\x3', '\x2', '\x2', '\x2', + '\xA7', '\x248', '\x3', '\x2', '\x2', '\x2', '\xA9', '\x24A', '\x3', '\x2', + '\x2', '\x2', '\xAB', '\x24C', '\x3', '\x2', '\x2', '\x2', '\xAD', '\x24F', + '\x3', '\x2', '\x2', '\x2', '\xAF', '\x252', '\x3', '\x2', '\x2', '\x2', + '\xB1', '\x255', '\x3', '\x2', '\x2', '\x2', '\xB3', '\x257', '\x3', '\x2', + '\x2', '\x2', '\xB5', '\x259', '\x3', '\x2', '\x2', '\x2', '\xB7', '\x25C', + '\x3', '\x2', '\x2', '\x2', '\xB9', '\x25E', '\x3', '\x2', '\x2', '\x2', + '\xBB', '\x260', '\x3', '\x2', '\x2', '\x2', '\xBD', '\x262', '\x3', '\x2', + '\x2', '\x2', '\xBF', '\x264', '\x3', '\x2', '\x2', '\x2', '\xC1', '\x266', + '\x3', '\x2', '\x2', '\x2', '\xC3', '\x268', '\x3', '\x2', '\x2', '\x2', + '\xC5', '\x26A', '\x3', '\x2', '\x2', '\x2', '\xC7', '\x26C', '\x3', '\x2', + '\x2', '\x2', '\xC9', '\x26E', '\x3', '\x2', '\x2', '\x2', '\xCB', '\x270', + '\x3', '\x2', '\x2', '\x2', '\xCD', '\x296', '\x3', '\x2', '\x2', '\x2', + '\xCF', '\x298', '\x3', '\x2', '\x2', '\x2', '\xD1', '\x29B', '\x3', '\x2', + '\x2', '\x2', '\xD3', '\x29D', '\x3', '\x2', '\x2', '\x2', '\xD5', '\x29F', + '\x3', '\x2', '\x2', '\x2', '\xD7', '\x2AE', '\x3', '\x2', '\x2', '\x2', + '\xD9', '\x2BE', '\x3', '\x2', '\x2', '\x2', '\xDB', '\x2D2', '\x3', '\x2', + '\x2', '\x2', '\xDD', '\x2D6', '\x3', '\x2', '\x2', '\x2', '\xDF', '\x2DF', + '\x3', '\x2', '\x2', '\x2', '\xE1', '\x2ED', '\x3', '\x2', '\x2', '\x2', + '\xE3', '\x2F0', '\x3', '\x2', '\x2', '\x2', '\xE5', '\x2F5', '\x3', '\x2', + '\x2', '\x2', '\xE7', '\x2F9', '\x3', '\x2', '\x2', '\x2', '\xE9', '\x2FC', + '\x3', '\x2', '\x2', '\x2', '\xEB', '\x301', '\x3', '\x2', '\x2', '\x2', + '\xED', '\x303', '\x3', '\x2', '\x2', '\x2', '\xEF', '\x305', '\x3', '\x2', + '\x2', '\x2', '\xF1', '\xF2', '\t', '\x2', '\x2', '\x2', '\xF2', '\x4', + '\x3', '\x2', '\x2', '\x2', '\xF3', '\xF4', '\t', '\x3', '\x2', '\x2', + '\xF4', '\x6', '\x3', '\x2', '\x2', '\x2', '\xF5', '\xF6', '\t', '\x4', + '\x2', '\x2', '\xF6', '\b', '\x3', '\x2', '\x2', '\x2', '\xF7', '\xF8', + '\t', '\x5', '\x2', '\x2', '\xF8', '\n', '\x3', '\x2', '\x2', '\x2', '\xF9', + '\xFA', '\t', '\x6', '\x2', '\x2', '\xFA', '\f', '\x3', '\x2', '\x2', + '\x2', '\xFB', '\xFC', '\t', '\a', '\x2', '\x2', '\xFC', '\xE', '\x3', + '\x2', '\x2', '\x2', '\xFD', '\xFE', '\t', '\b', '\x2', '\x2', '\xFE', + '\x10', '\x3', '\x2', '\x2', '\x2', '\xFF', '\x100', '\t', '\t', '\x2', + '\x2', '\x100', '\x12', '\x3', '\x2', '\x2', '\x2', '\x101', '\x102', + '\t', '\n', '\x2', '\x2', '\x102', '\x14', '\x3', '\x2', '\x2', '\x2', + '\x103', '\x104', '\t', '\v', '\x2', '\x2', '\x104', '\x16', '\x3', '\x2', + '\x2', '\x2', '\x105', '\x106', '\t', '\f', '\x2', '\x2', '\x106', '\x18', + '\x3', '\x2', '\x2', '\x2', '\x107', '\x108', '\t', '\r', '\x2', '\x2', + '\x108', '\x1A', '\x3', '\x2', '\x2', '\x2', '\x109', '\x10A', '\t', '\xE', + '\x2', '\x2', '\x10A', '\x1C', '\x3', '\x2', '\x2', '\x2', '\x10B', '\x10C', + '\t', '\xF', '\x2', '\x2', '\x10C', '\x1E', '\x3', '\x2', '\x2', '\x2', + '\x10D', '\x10E', '\t', '\x10', '\x2', '\x2', '\x10E', ' ', '\x3', '\x2', + '\x2', '\x2', '\x10F', '\x110', '\t', '\x11', '\x2', '\x2', '\x110', '\"', + '\x3', '\x2', '\x2', '\x2', '\x111', '\x112', '\t', '\x12', '\x2', '\x2', + '\x112', '$', '\x3', '\x2', '\x2', '\x2', '\x113', '\x114', '\t', '\x13', + '\x2', '\x2', '\x114', '&', '\x3', '\x2', '\x2', '\x2', '\x115', '\x116', + '\t', '\x14', '\x2', '\x2', '\x116', '(', '\x3', '\x2', '\x2', '\x2', + '\x117', '\x118', '\t', '\x15', '\x2', '\x2', '\x118', '*', '\x3', '\x2', + '\x2', '\x2', '\x119', '\x11A', '\t', '\x16', '\x2', '\x2', '\x11A', ',', + '\x3', '\x2', '\x2', '\x2', '\x11B', '\x11C', '\t', '\x17', '\x2', '\x2', + '\x11C', '.', '\x3', '\x2', '\x2', '\x2', '\x11D', '\x11E', '\t', '\x18', + '\x2', '\x2', '\x11E', '\x30', '\x3', '\x2', '\x2', '\x2', '\x11F', '\x120', + '\t', '\x19', '\x2', '\x2', '\x120', '\x32', '\x3', '\x2', '\x2', '\x2', + '\x121', '\x122', '\t', '\x1A', '\x2', '\x2', '\x122', '\x34', '\x3', + '\x2', '\x2', '\x2', '\x123', '\x124', '\t', '\x1B', '\x2', '\x2', '\x124', + '\x36', '\x3', '\x2', '\x2', '\x2', '\x125', '\x126', '\t', '\x1C', '\x2', + '\x2', '\x126', '\x38', '\x3', '\x2', '\x2', '\x2', '\x127', '\x129', + '\x5', '\x37', '\x1C', '\x2', '\x128', '\x127', '\x3', '\x2', '\x2', '\x2', + '\x129', '\x12A', '\x3', '\x2', '\x2', '\x2', '\x12A', '\x128', '\x3', + '\x2', '\x2', '\x2', '\x12A', '\x12B', '\x3', '\x2', '\x2', '\x2', '\x12B', + ':', '\x3', '\x2', '\x2', '\x2', '\x12C', '\x12D', '\t', '\x1D', '\x2', + '\x2', '\x12D', '<', '\x3', '\x2', '\x2', '\x2', '\x12E', '\x12F', '\a', + '\x32', '\x2', '\x2', '\x12F', '\x130', '\a', 'z', '\x2', '\x2', '\x130', + '\x132', '\x3', '\x2', '\x2', '\x2', '\x131', '\x133', '\x5', ';', '\x1E', + '\x2', '\x132', '\x131', '\x3', '\x2', '\x2', '\x2', '\x133', '\x134', + '\x3', '\x2', '\x2', '\x2', '\x134', '\x132', '\x3', '\x2', '\x2', '\x2', + '\x134', '\x135', '\x3', '\x2', '\x2', '\x2', '\x135', '\x141', '\x3', + '\x2', '\x2', '\x2', '\x136', '\x137', '\a', 'z', '\x2', '\x2', '\x137', + '\x138', '\a', ')', '\x2', '\x2', '\x138', '\x13A', '\x3', '\x2', '\x2', + '\x2', '\x139', '\x13B', '\x5', ';', '\x1E', '\x2', '\x13A', '\x139', + '\x3', '\x2', '\x2', '\x2', '\x13B', '\x13C', '\x3', '\x2', '\x2', '\x2', + '\x13C', '\x13A', '\x3', '\x2', '\x2', '\x2', '\x13C', '\x13D', '\x3', + '\x2', '\x2', '\x2', '\x13D', '\x13E', '\x3', '\x2', '\x2', '\x2', '\x13E', + '\x13F', '\a', ')', '\x2', '\x2', '\x13F', '\x141', '\x3', '\x2', '\x2', + '\x2', '\x140', '\x12E', '\x3', '\x2', '\x2', '\x2', '\x140', '\x136', + '\x3', '\x2', '\x2', '\x2', '\x141', '>', '\x3', '\x2', '\x2', '\x2', + '\x142', '\x143', '\a', '\x32', '\x2', '\x2', '\x143', '\x144', '\a', + '\x64', '\x2', '\x2', '\x144', '\x146', '\x3', '\x2', '\x2', '\x2', '\x145', + '\x147', '\t', '\x1E', '\x2', '\x2', '\x146', '\x145', '\x3', '\x2', '\x2', + '\x2', '\x147', '\x148', '\x3', '\x2', '\x2', '\x2', '\x148', '\x146', + '\x3', '\x2', '\x2', '\x2', '\x148', '\x149', '\x3', '\x2', '\x2', '\x2', + '\x149', '\x154', '\x3', '\x2', '\x2', '\x2', '\x14A', '\x14B', '\a', + '\x64', '\x2', '\x2', '\x14B', '\x14C', '\a', ')', '\x2', '\x2', '\x14C', + '\x14E', '\x3', '\x2', '\x2', '\x2', '\x14D', '\x14F', '\t', '\x1E', '\x2', + '\x2', '\x14E', '\x14D', '\x3', '\x2', '\x2', '\x2', '\x14F', '\x150', + '\x3', '\x2', '\x2', '\x2', '\x150', '\x14E', '\x3', '\x2', '\x2', '\x2', + '\x150', '\x151', '\x3', '\x2', '\x2', '\x2', '\x151', '\x152', '\x3', + '\x2', '\x2', '\x2', '\x152', '\x154', '\a', ')', '\x2', '\x2', '\x153', + '\x142', '\x3', '\x2', '\x2', '\x2', '\x153', '\x14A', '\x3', '\x2', '\x2', + '\x2', '\x154', '@', '\x3', '\x2', '\x2', '\x2', '\x155', '\x156', '\x5', + '\x39', '\x1D', '\x2', '\x156', '\x42', '\x3', '\x2', '\x2', '\x2', '\x157', + '\x159', '\x5', '\x39', '\x1D', '\x2', '\x158', '\x157', '\x3', '\x2', + '\x2', '\x2', '\x158', '\x159', '\x3', '\x2', '\x2', '\x2', '\x159', '\x15A', + '\x3', '\x2', '\x2', '\x2', '\x15A', '\x15B', '\x5', '\xB9', ']', '\x2', + '\x15B', '\x15C', '\x5', '\x39', '\x1D', '\x2', '\x15C', '\x44', '\x3', + '\x2', '\x2', '\x2', '\x15D', '\x15F', '\x5', '\x39', '\x1D', '\x2', '\x15E', + '\x15D', '\x3', '\x2', '\x2', '\x2', '\x15E', '\x15F', '\x3', '\x2', '\x2', + '\x2', '\x15F', '\x160', '\x3', '\x2', '\x2', '\x2', '\x160', '\x162', + '\x5', '\xB9', ']', '\x2', '\x161', '\x15E', '\x3', '\x2', '\x2', '\x2', + '\x161', '\x162', '\x3', '\x2', '\x2', '\x2', '\x162', '\x163', '\x3', + '\x2', '\x2', '\x2', '\x163', '\x164', '\x5', '\x39', '\x1D', '\x2', '\x164', + '\x167', '\t', '\x6', '\x2', '\x2', '\x165', '\x168', '\x5', '\x9F', 'P', + '\x2', '\x166', '\x168', '\x5', '\x9D', 'O', '\x2', '\x167', '\x165', + '\x3', '\x2', '\x2', '\x2', '\x167', '\x166', '\x3', '\x2', '\x2', '\x2', + '\x167', '\x168', '\x3', '\x2', '\x2', '\x2', '\x168', '\x169', '\x3', + '\x2', '\x2', '\x2', '\x169', '\x16A', '\x5', '\x39', '\x1D', '\x2', '\x16A', + '\x46', '\x3', '\x2', '\x2', '\x2', '\x16B', '\x16C', '\x5', '\'', '\x14', + '\x2', '\x16C', '\x16D', '\x5', '\x11', '\t', '\x2', '\x16D', '\x16E', + '\x5', '\x1F', '\x10', '\x2', '\x16E', '\x16F', '\x5', '/', '\x18', '\x2', + '\x16F', 'H', '\x3', '\x2', '\x2', '\x2', '\x170', '\x171', '\x5', '\v', + '\x6', '\x2', '\x171', '\x172', '\x5', '\x31', '\x19', '\x2', '\x172', + '\x173', '\x5', '\v', '\x6', '\x2', '\x173', '\x174', '\x5', '\a', '\x4', + '\x2', '\x174', '\x175', '\x5', '\r', '\a', '\x2', '\x175', '\x176', '\x5', + '\x13', '\n', '\x2', '\x176', '\x177', '\x5', '\x19', '\r', '\x2', '\x177', + '\x178', '\x5', '\v', '\x6', '\x2', '\x178', 'J', '\x3', '\x2', '\x2', + '\x2', '\x179', '\x17A', '\x5', '#', '\x12', '\x2', '\x17A', '\x17B', + '\x5', '+', '\x16', '\x2', '\x17B', '\x17C', '\x5', '\x13', '\n', '\x2', + '\x17C', '\x17D', '\x5', ')', '\x15', '\x2', '\x17D', 'L', '\x3', '\x2', + '\x2', '\x2', '\x17E', '\x17F', '\x5', '\x3', '\x2', '\x2', '\x17F', '\x180', + '\x5', '\x1D', '\xF', '\x2', '\x180', '\x181', '\x5', '\t', '\x5', '\x2', + '\x181', 'N', '\x3', '\x2', '\x2', '\x2', '\x182', '\x183', '\x5', '\x3', + '\x2', '\x2', '\x183', '\x184', '\x5', '\'', '\x14', '\x2', '\x184', '\x185', + '\x5', '\a', '\x4', '\x2', '\x185', 'P', '\x3', '\x2', '\x2', '\x2', '\x186', + '\x187', '\x5', '\x3', '\x2', '\x2', '\x187', '\x188', '\x5', '\'', '\x14', + '\x2', '\x188', 'R', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\x5', + '\x5', '\x3', '\x2', '\x18A', '\x18B', '\x5', '\v', '\x6', '\x2', '\x18B', + '\x18C', '\x5', '\xF', '\b', '\x2', '\x18C', '\x18D', '\x5', '\x13', '\n', + '\x2', '\x18D', '\x18E', '\x5', '\x1D', '\xF', '\x2', '\x18E', 'T', '\x3', + '\x2', '\x2', '\x2', '\x18F', '\x190', '\x5', '\x5', '\x3', '\x2', '\x190', + '\x191', '\x5', '\x33', '\x1A', '\x2', '\x191', 'V', '\x3', '\x2', '\x2', + '\x2', '\x192', '\x193', '\x5', '\a', '\x4', '\x2', '\x193', '\x194', + '\x5', '\x11', '\t', '\x2', '\x194', '\x195', '\x5', '\x3', '\x2', '\x2', + '\x195', '\x196', '\x5', '%', '\x13', '\x2', '\x196', 'X', '\x3', '\x2', + '\x2', '\x2', '\x197', '\x198', '\x5', '\a', '\x4', '\x2', '\x198', '\x199', + '\x5', '%', '\x13', '\x2', '\x199', '\x19A', '\x5', '\v', '\x6', '\x2', + '\x19A', '\x19B', '\x5', '\x3', '\x2', '\x2', '\x19B', '\x19C', '\x5', + ')', '\x15', '\x2', '\x19C', '\x19D', '\x5', '\v', '\x6', '\x2', '\x19D', + 'Z', '\x3', '\x2', '\x2', '\x2', '\x19E', '\x19F', '\x5', '\t', '\x5', + '\x2', '\x19F', '\x1A0', '\x5', '\v', '\x6', '\x2', '\x1A0', '\x1A1', + '\x5', '\x19', '\r', '\x2', '\x1A1', '\x1A2', '\x5', '\v', '\x6', '\x2', + '\x1A2', '\x1A3', '\x5', ')', '\x15', '\x2', '\x1A3', '\x1A4', '\x5', + '\v', '\x6', '\x2', '\x1A4', '\\', '\x3', '\x2', '\x2', '\x2', '\x1A5', + '\x1A6', '\x5', '\t', '\x5', '\x2', '\x1A6', '\x1A7', '\x5', '\v', '\x6', + '\x2', '\x1A7', '\x1A8', '\x5', '\'', '\x14', '\x2', '\x1A8', '\x1A9', + '\x5', '\a', '\x4', '\x2', '\x1A9', '^', '\x3', '\x2', '\x2', '\x2', '\x1AA', + '\x1AB', '\x5', '\t', '\x5', '\x2', '\x1AB', '\x1AC', '\x5', '%', '\x13', + '\x2', '\x1AC', '\x1AD', '\x5', '\x1F', '\x10', '\x2', '\x1AD', '\x1AE', + '\x5', '!', '\x11', '\x2', '\x1AE', '`', '\x3', '\x2', '\x2', '\x2', '\x1AF', + '\x1B0', '\x5', '\r', '\a', '\x2', '\x1B0', '\x1B1', '\x5', '\x19', '\r', + '\x2', '\x1B1', '\x1B2', '\x5', '\x1F', '\x10', '\x2', '\x1B2', '\x1B3', + '\x5', '\x3', '\x2', '\x2', '\x1B3', '\x1B4', '\x5', ')', '\x15', '\x2', + '\x1B4', '\x62', '\x3', '\x2', '\x2', '\x2', '\x1B5', '\x1B6', '\x5', + '\r', '\a', '\x2', '\x1B6', '\x1B7', '\x5', '%', '\x13', '\x2', '\x1B7', + '\x1B8', '\x5', '\x1F', '\x10', '\x2', '\x1B8', '\x1B9', '\x5', '\x1B', + '\xE', '\x2', '\x1B9', '\x64', '\x3', '\x2', '\x2', '\x2', '\x1BA', '\x1BB', + '\x5', '\x13', '\n', '\x2', '\x1BB', '\x1BC', '\x5', '\x1D', '\xF', '\x2', + '\x1BC', '\x1BD', '\x5', '\t', '\x5', '\x2', '\x1BD', '\x1BE', '\x5', + '\v', '\x6', '\x2', '\x1BE', '\x1BF', '\x5', '\x31', '\x19', '\x2', '\x1BF', + '\x66', '\x3', '\x2', '\x2', '\x2', '\x1C0', '\x1C1', '\x5', '\x13', '\n', + '\x2', '\x1C1', '\x1C2', '\x5', '\x1D', '\xF', '\x2', '\x1C2', '\x1C3', + '\x5', '\'', '\x14', '\x2', '\x1C3', '\x1C4', '\x5', '\v', '\x6', '\x2', + '\x1C4', '\x1C5', '\x5', '%', '\x13', '\x2', '\x1C5', '\x1C6', '\x5', + ')', '\x15', '\x2', '\x1C6', 'h', '\x3', '\x2', '\x2', '\x2', '\x1C7', + '\x1C8', '\x5', '\x13', '\n', '\x2', '\x1C8', '\x1C9', '\x5', '\x1D', + '\xF', '\x2', '\x1C9', '\x1CA', '\x5', ')', '\x15', '\x2', '\x1CA', '\x1CB', + '\x5', '\x1F', '\x10', '\x2', '\x1CB', 'j', '\x3', '\x2', '\x2', '\x2', + '\x1CC', '\x1CD', '\x5', '\x13', '\n', '\x2', '\x1CD', '\x1CE', '\x5', + '\x1D', '\xF', '\x2', '\x1CE', '\x1CF', '\x5', ')', '\x15', '\x2', '\x1CF', + 'l', '\x3', '\x2', '\x2', '\x2', '\x1D0', '\x1D1', '\x5', '\x17', '\f', + '\x2', '\x1D1', '\x1D2', '\x5', '\v', '\x6', '\x2', '\x1D2', '\x1D3', + '\x5', '\x33', '\x1A', '\x2', '\x1D3', 'n', '\x3', '\x2', '\x2', '\x2', + '\x1D4', '\x1D5', '\x5', '\x1D', '\xF', '\x2', '\x1D5', '\x1D6', '\x5', + '\x1F', '\x10', '\x2', '\x1D6', '\x1D7', '\x5', ')', '\x15', '\x2', '\x1D7', + 'p', '\x3', '\x2', '\x2', '\x2', '\x1D8', '\x1D9', '\x5', '\x1F', '\x10', + '\x2', '\x1D9', '\x1DA', '\x5', '\x1D', '\xF', '\x2', '\x1DA', 'r', '\x3', + '\x2', '\x2', '\x2', '\x1DB', '\x1DC', '\x5', '\x1F', '\x10', '\x2', '\x1DC', + '\x1DD', '\x5', '%', '\x13', '\x2', '\x1DD', '\x1DE', '\x5', '\t', '\x5', + '\x2', '\x1DE', '\x1DF', '\x5', '\v', '\x6', '\x2', '\x1DF', '\x1E0', + '\x5', '%', '\x13', '\x2', '\x1E0', 't', '\x3', '\x2', '\x2', '\x2', '\x1E1', + '\x1E2', '\x5', '\x1F', '\x10', '\x2', '\x1E2', '\x1E3', '\x5', '%', '\x13', + '\x2', '\x1E3', 'v', '\x3', '\x2', '\x2', '\x2', '\x1E4', '\x1E5', '\x5', + '!', '\x11', '\x2', '\x1E5', '\x1E6', '\x5', '%', '\x13', '\x2', '\x1E6', + '\x1E7', '\x5', '\x13', '\n', '\x2', '\x1E7', '\x1E8', '\x5', '\x1B', + '\xE', '\x2', '\x1E8', '\x1E9', '\x5', '\x3', '\x2', '\x2', '\x1E9', '\x1EA', + '\x5', '%', '\x13', '\x2', '\x1EA', '\x1EB', '\x5', '\x33', '\x1A', '\x2', + '\x1EB', 'x', '\x3', '\x2', '\x2', '\x2', '\x1EC', '\x1ED', '\x5', '\'', + '\x14', '\x2', '\x1ED', '\x1EE', '\x5', '\v', '\x6', '\x2', '\x1EE', '\x1EF', + '\x5', '\x19', '\r', '\x2', '\x1EF', '\x1F0', '\x5', '\v', '\x6', '\x2', + '\x1F0', '\x1F1', '\x5', '\a', '\x4', '\x2', '\x1F1', '\x1F2', '\x5', + ')', '\x15', '\x2', '\x1F2', 'z', '\x3', '\x2', '\x2', '\x2', '\x1F3', + '\x1F4', '\x5', ')', '\x15', '\x2', '\x1F4', '\x1F5', '\x5', '\x3', '\x2', + '\x2', '\x1F5', '\x1F6', '\x5', '\x5', '\x3', '\x2', '\x1F6', '\x1F7', + '\x5', '\x19', '\r', '\x2', '\x1F7', '\x1F8', '\x5', '\v', '\x6', '\x2', + '\x1F8', '\x1F9', '\x5', '\'', '\x14', '\x2', '\x1F9', '|', '\x3', '\x2', + '\x2', '\x2', '\x1FA', '\x1FB', '\x5', ')', '\x15', '\x2', '\x1FB', '\x1FC', + '\x5', '\x3', '\x2', '\x2', '\x1FC', '\x1FD', '\x5', '\x5', '\x3', '\x2', + '\x1FD', '\x1FE', '\x5', '\x19', '\r', '\x2', '\x1FE', '\x1FF', '\x5', + '\v', '\x6', '\x2', '\x1FF', '~', '\x3', '\x2', '\x2', '\x2', '\x200', + '\x201', '\x5', '+', '\x16', '\x2', '\x201', '\x202', '\x5', '\x1D', '\xF', + '\x2', '\x202', '\x203', '\x5', '\x13', '\n', '\x2', '\x203', '\x204', + '\x5', '#', '\x12', '\x2', '\x204', '\x205', '\x5', '+', '\x16', '\x2', + '\x205', '\x206', '\x5', '\v', '\x6', '\x2', '\x206', '\x80', '\x3', '\x2', + '\x2', '\x2', '\x207', '\x208', '\x5', '-', '\x17', '\x2', '\x208', '\x209', + '\x5', '\x3', '\x2', '\x2', '\x209', '\x20A', '\x5', '\x19', '\r', '\x2', + '\x20A', '\x20B', '\x5', '+', '\x16', '\x2', '\x20B', '\x20C', '\x5', + '\v', '\x6', '\x2', '\x20C', '\x20D', '\x5', '\'', '\x14', '\x2', '\x20D', + '\x82', '\x3', '\x2', '\x2', '\x2', '\x20E', '\x20F', '\x5', '-', '\x17', + '\x2', '\x20F', '\x210', '\x5', '\x3', '\x2', '\x2', '\x210', '\x211', + '\x5', '\x19', '\r', '\x2', '\x211', '\x212', '\x5', '+', '\x16', '\x2', + '\x212', '\x213', '\x5', '\v', '\x6', '\x2', '\x213', '\x84', '\x3', '\x2', + '\x2', '\x2', '\x214', '\x215', '\x5', '/', '\x18', '\x2', '\x215', '\x216', + '\x5', '\x11', '\t', '\x2', '\x216', '\x217', '\x5', '\v', '\x6', '\x2', + '\x217', '\x218', '\x5', '%', '\x13', '\x2', '\x218', '\x219', '\x5', + '\v', '\x6', '\x2', '\x219', '\x86', '\x3', '\x2', '\x2', '\x2', '\x21A', + '\x21B', '\x5', '/', '\x18', '\x2', '\x21B', '\x21C', '\x5', '\x1F', '\x10', + '\x2', '\x21C', '\x21D', '\x5', '%', '\x13', '\x2', '\x21D', '\x21E', + '\x5', '\x17', '\f', '\x2', '\x21E', '\x88', '\x3', '\x2', '\x2', '\x2', + '\x21F', '\x220', '\x5', '\x31', '\x19', '\x2', '\x220', '\x221', '\x5', + '\x1F', '\x10', '\x2', '\x221', '\x222', '\x5', '%', '\x13', '\x2', '\x222', + '\x8A', '\x3', '\x2', '\x2', '\x2', '\x223', '\x224', '\a', '?', '\x2', + '\x2', '\x224', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x225', '\x226', + '\a', '<', '\x2', '\x2', '\x226', '\x227', '\a', '?', '\x2', '\x2', '\x227', + '\x8E', '\x3', '\x2', '\x2', '\x2', '\x228', '\x229', '\a', '>', '\x2', + '\x2', '\x229', '\x22A', '\a', '?', '\x2', '\x2', '\x22A', '\x22B', '\a', + '@', '\x2', '\x2', '\x22B', '\x90', '\x3', '\x2', '\x2', '\x2', '\x22C', + '\x22D', '\a', '@', '\x2', '\x2', '\x22D', '\x22E', '\a', '?', '\x2', + '\x2', '\x22E', '\x92', '\x3', '\x2', '\x2', '\x2', '\x22F', '\x230', + '\a', '@', '\x2', '\x2', '\x230', '\x94', '\x3', '\x2', '\x2', '\x2', + '\x231', '\x232', '\a', '>', '\x2', '\x2', '\x232', '\x233', '\a', '?', + '\x2', '\x2', '\x233', '\x96', '\x3', '\x2', '\x2', '\x2', '\x234', '\x235', + '\a', '>', '\x2', '\x2', '\x235', '\x98', '\x3', '\x2', '\x2', '\x2', + '\x236', '\x237', '\a', '#', '\x2', '\x2', '\x237', '\x238', '\a', '?', + '\x2', '\x2', '\x238', '\x9A', '\x3', '\x2', '\x2', '\x2', '\x239', '\x23A', + '\a', '>', '\x2', '\x2', '\x23A', '\x23B', '\a', '@', '\x2', '\x2', '\x23B', + '\x23C', '\x3', '\x2', '\x2', '\x2', '\x23C', '\x23D', '\b', 'N', '\x2', + '\x2', '\x23D', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x23E', '\x23F', + '\a', '-', '\x2', '\x2', '\x23F', '\x9E', '\x3', '\x2', '\x2', '\x2', + '\x240', '\x241', '\a', '/', '\x2', '\x2', '\x241', '\xA0', '\x3', '\x2', + '\x2', '\x2', '\x242', '\x243', '\a', ',', '\x2', '\x2', '\x243', '\xA2', + '\x3', '\x2', '\x2', '\x2', '\x244', '\x245', '\a', '\x31', '\x2', '\x2', + '\x245', '\xA4', '\x3', '\x2', '\x2', '\x2', '\x246', '\x247', '\a', '\'', + '\x2', '\x2', '\x247', '\xA6', '\x3', '\x2', '\x2', '\x2', '\x248', '\x249', + '\a', '#', '\x2', '\x2', '\x249', '\xA8', '\x3', '\x2', '\x2', '\x2', + '\x24A', '\x24B', '\a', '\x80', '\x2', '\x2', '\x24B', '\xAA', '\x3', + '\x2', '\x2', '\x2', '\x24C', '\x24D', '\a', '>', '\x2', '\x2', '\x24D', + '\x24E', '\a', '>', '\x2', '\x2', '\x24E', '\xAC', '\x3', '\x2', '\x2', + '\x2', '\x24F', '\x250', '\a', '@', '\x2', '\x2', '\x250', '\x251', '\a', + '@', '\x2', '\x2', '\x251', '\xAE', '\x3', '\x2', '\x2', '\x2', '\x252', + '\x253', '\a', '(', '\x2', '\x2', '\x253', '\x254', '\a', '(', '\x2', + '\x2', '\x254', '\xB0', '\x3', '\x2', '\x2', '\x2', '\x255', '\x256', + '\a', '(', '\x2', '\x2', '\x256', '\xB2', '\x3', '\x2', '\x2', '\x2', + '\x257', '\x258', '\a', '`', '\x2', '\x2', '\x258', '\xB4', '\x3', '\x2', + '\x2', '\x2', '\x259', '\x25A', '\a', '~', '\x2', '\x2', '\x25A', '\x25B', + '\a', '~', '\x2', '\x2', '\x25B', '\xB6', '\x3', '\x2', '\x2', '\x2', + '\x25C', '\x25D', '\a', '~', '\x2', '\x2', '\x25D', '\xB8', '\x3', '\x2', + '\x2', '\x2', '\x25E', '\x25F', '\a', '\x30', '\x2', '\x2', '\x25F', '\xBA', + '\x3', '\x2', '\x2', '\x2', '\x260', '\x261', '\a', '.', '\x2', '\x2', + '\x261', '\xBC', '\x3', '\x2', '\x2', '\x2', '\x262', '\x263', '\a', '=', + '\x2', '\x2', '\x263', '\xBE', '\x3', '\x2', '\x2', '\x2', '\x264', '\x265', + '\a', '<', '\x2', '\x2', '\x265', '\xC0', '\x3', '\x2', '\x2', '\x2', + '\x266', '\x267', '\a', '*', '\x2', '\x2', '\x267', '\xC2', '\x3', '\x2', + '\x2', '\x2', '\x268', '\x269', '\a', '+', '\x2', '\x2', '\x269', '\xC4', + '\x3', '\x2', '\x2', '\x2', '\x26A', '\x26B', '\a', '}', '\x2', '\x2', + '\x26B', '\xC6', '\x3', '\x2', '\x2', '\x2', '\x26C', '\x26D', '\a', '\x7F', + '\x2', '\x2', '\x26D', '\xC8', '\x3', '\x2', '\x2', '\x2', '\x26E', '\x26F', + '\a', '\x61', '\x2', '\x2', '\x26F', '\xCA', '\x3', '\x2', '\x2', '\x2', + '\x270', '\x271', '\t', '\x1F', '\x2', '\x2', '\x271', '\x272', '\x3', + '\x2', '\x2', '\x2', '\x272', '\x273', '\b', '\x66', '\x3', '\x2', '\x273', + '\xCC', '\x3', '\x2', '\x2', '\x2', '\x274', '\x276', '\x5', '\x39', '\x1D', + '\x2', '\x275', '\x274', '\x3', '\x2', '\x2', '\x2', '\x276', '\x277', '\x3', '\x2', '\x2', '\x2', '\x277', '\x275', '\x3', '\x2', '\x2', '\x2', - '\x277', '\x278', '\x3', '\x2', '\x2', '\x2', '\x278', '\x27B', '\x3', - '\x2', '\x2', '\x2', '\x279', '\x277', '\x3', '\x2', '\x2', '\x2', '\x27A', - '\x273', '\x3', '\x2', '\x2', '\x2', '\x27A', '\x27B', '\x3', '\x2', '\x2', - '\x2', '\x27B', '\x290', '\x3', '\x2', '\x2', '\x2', '\x27C', '\x27E', - '\x5', '\x39', '\x1D', '\x2', '\x27D', '\x27C', '\x3', '\x2', '\x2', '\x2', - '\x27E', '\x27F', '\x3', '\x2', '\x2', '\x2', '\x27F', '\x27D', '\x3', - '\x2', '\x2', '\x2', '\x27F', '\x280', '\x3', '\x2', '\x2', '\x2', '\x280', - '\x281', '\x3', '\x2', '\x2', '\x2', '\x281', '\x285', '\x5', '\xED', - 'w', '\x2', '\x282', '\x284', '\x5', '\xE9', 'u', '\x2', '\x283', '\x282', - '\x3', '\x2', '\x2', '\x2', '\x284', '\x287', '\x3', '\x2', '\x2', '\x2', - '\x285', '\x283', '\x3', '\x2', '\x2', '\x2', '\x285', '\x286', '\x3', - '\x2', '\x2', '\x2', '\x286', '\x290', '\x3', '\x2', '\x2', '\x2', '\x287', - '\x285', '\x3', '\x2', '\x2', '\x2', '\x288', '\x28C', '\x5', '\xEB', - 'v', '\x2', '\x289', '\x28B', '\x5', '\xE9', 'u', '\x2', '\x28A', '\x289', + '\x277', '\x278', '\x3', '\x2', '\x2', '\x2', '\x278', '\x279', '\x3', + '\x2', '\x2', '\x2', '\x279', '\x281', '\t', '\x6', '\x2', '\x2', '\x27A', + '\x27E', '\x5', '\xED', 'w', '\x2', '\x27B', '\x27D', '\x5', '\xEB', 'v', + '\x2', '\x27C', '\x27B', '\x3', '\x2', '\x2', '\x2', '\x27D', '\x280', + '\x3', '\x2', '\x2', '\x2', '\x27E', '\x27C', '\x3', '\x2', '\x2', '\x2', + '\x27E', '\x27F', '\x3', '\x2', '\x2', '\x2', '\x27F', '\x282', '\x3', + '\x2', '\x2', '\x2', '\x280', '\x27E', '\x3', '\x2', '\x2', '\x2', '\x281', + '\x27A', '\x3', '\x2', '\x2', '\x2', '\x281', '\x282', '\x3', '\x2', '\x2', + '\x2', '\x282', '\x297', '\x3', '\x2', '\x2', '\x2', '\x283', '\x285', + '\x5', '\x39', '\x1D', '\x2', '\x284', '\x283', '\x3', '\x2', '\x2', '\x2', + '\x285', '\x286', '\x3', '\x2', '\x2', '\x2', '\x286', '\x284', '\x3', + '\x2', '\x2', '\x2', '\x286', '\x287', '\x3', '\x2', '\x2', '\x2', '\x287', + '\x288', '\x3', '\x2', '\x2', '\x2', '\x288', '\x28C', '\x5', '\xEF', + 'x', '\x2', '\x289', '\x28B', '\x5', '\xEB', 'v', '\x2', '\x28A', '\x289', '\x3', '\x2', '\x2', '\x2', '\x28B', '\x28E', '\x3', '\x2', '\x2', '\x2', '\x28C', '\x28A', '\x3', '\x2', '\x2', '\x2', '\x28C', '\x28D', '\x3', - '\x2', '\x2', '\x2', '\x28D', '\x290', '\x3', '\x2', '\x2', '\x2', '\x28E', - '\x28C', '\x3', '\x2', '\x2', '\x2', '\x28F', '\x26E', '\x3', '\x2', '\x2', - '\x2', '\x28F', '\x27D', '\x3', '\x2', '\x2', '\x2', '\x28F', '\x288', - '\x3', '\x2', '\x2', '\x2', '\x290', '\xCC', '\x3', '\x2', '\x2', '\x2', - '\x291', '\x292', '\t', '\xF', '\x2', '\x2', '\x292', '\x293', '\x5', - '\xD7', 'l', '\x2', '\x293', '\xCE', '\x3', '\x2', '\x2', '\x2', '\x294', - '\x295', '\a', '\x62', '\x2', '\x2', '\x295', '\xD0', '\x3', '\x2', '\x2', - '\x2', '\x296', '\x297', '\a', ')', '\x2', '\x2', '\x297', '\xD2', '\x3', - '\x2', '\x2', '\x2', '\x298', '\x299', '\a', '$', '\x2', '\x2', '\x299', - '\xD4', '\x3', '\x2', '\x2', '\x2', '\x29A', '\x2A2', '\x5', '\xD3', 'j', - '\x2', '\x29B', '\x29C', '\a', '^', '\x2', '\x2', '\x29C', '\x29E', '\v', - '\x2', '\x2', '\x2', '\x29D', '\x29B', '\x3', '\x2', '\x2', '\x2', '\x29D', - '\x29E', '\x3', '\x2', '\x2', '\x2', '\x29E', '\x29F', '\x3', '\x2', '\x2', - '\x2', '\x29F', '\x2A1', '\v', '\x2', '\x2', '\x2', '\x2A0', '\x29D', - '\x3', '\x2', '\x2', '\x2', '\x2A1', '\x2A4', '\x3', '\x2', '\x2', '\x2', - '\x2A2', '\x2A3', '\x3', '\x2', '\x2', '\x2', '\x2A2', '\x2A0', '\x3', - '\x2', '\x2', '\x2', '\x2A3', '\x2A5', '\x3', '\x2', '\x2', '\x2', '\x2A4', - '\x2A2', '\x3', '\x2', '\x2', '\x2', '\x2A5', '\x2A6', '\x5', '\xD3', - 'j', '\x2', '\x2A6', '\x2A8', '\x3', '\x2', '\x2', '\x2', '\x2A7', '\x29A', - '\x3', '\x2', '\x2', '\x2', '\x2A8', '\x2A9', '\x3', '\x2', '\x2', '\x2', - '\x2A9', '\x2A7', '\x3', '\x2', '\x2', '\x2', '\x2A9', '\x2AA', '\x3', - '\x2', '\x2', '\x2', '\x2AA', '\xD6', '\x3', '\x2', '\x2', '\x2', '\x2AB', - '\x2B2', '\x5', '\xD1', 'i', '\x2', '\x2AC', '\x2AE', '\a', '^', '\x2', - '\x2', '\x2AD', '\x2AC', '\x3', '\x2', '\x2', '\x2', '\x2AD', '\x2AE', - '\x3', '\x2', '\x2', '\x2', '\x2AE', '\x2AF', '\x3', '\x2', '\x2', '\x2', - '\x2AF', '\x2B1', '\v', '\x2', '\x2', '\x2', '\x2B0', '\x2AD', '\x3', - '\x2', '\x2', '\x2', '\x2B1', '\x2B4', '\x3', '\x2', '\x2', '\x2', '\x2B2', - '\x2B3', '\x3', '\x2', '\x2', '\x2', '\x2B2', '\x2B0', '\x3', '\x2', '\x2', - '\x2', '\x2B3', '\x2B5', '\x3', '\x2', '\x2', '\x2', '\x2B4', '\x2B2', - '\x3', '\x2', '\x2', '\x2', '\x2B5', '\x2B6', '\x5', '\xD1', 'i', '\x2', - '\x2B6', '\x2B8', '\x3', '\x2', '\x2', '\x2', '\x2B7', '\x2AB', '\x3', - '\x2', '\x2', '\x2', '\x2B8', '\x2B9', '\x3', '\x2', '\x2', '\x2', '\x2B9', - '\x2B7', '\x3', '\x2', '\x2', '\x2', '\x2B9', '\x2BA', '\x3', '\x2', '\x2', - '\x2', '\x2BA', '\xD8', '\x3', '\x2', '\x2', '\x2', '\x2BB', '\x2BC', - '\a', '\x31', '\x2', '\x2', '\x2BC', '\x2BD', '\a', ',', '\x2', '\x2', - '\x2BD', '\x2BE', '\a', ',', '\x2', '\x2', '\x2BE', '\x2CC', '\a', '\x31', - '\x2', '\x2', '\x2BF', '\x2C0', '\a', '\x31', '\x2', '\x2', '\x2C0', '\x2C1', - '\a', ',', '\x2', '\x2', '\x2C1', '\x2C2', '\x3', '\x2', '\x2', '\x2', - '\x2C2', '\x2C6', '\n', ' ', '\x2', '\x2', '\x2C3', '\x2C5', '\v', '\x2', - '\x2', '\x2', '\x2C4', '\x2C3', '\x3', '\x2', '\x2', '\x2', '\x2C5', '\x2C8', - '\x3', '\x2', '\x2', '\x2', '\x2C6', '\x2C7', '\x3', '\x2', '\x2', '\x2', - '\x2C6', '\x2C4', '\x3', '\x2', '\x2', '\x2', '\x2C7', '\x2C9', '\x3', - '\x2', '\x2', '\x2', '\x2C8', '\x2C6', '\x3', '\x2', '\x2', '\x2', '\x2C9', - '\x2CA', '\a', ',', '\x2', '\x2', '\x2CA', '\x2CC', '\a', '\x31', '\x2', - '\x2', '\x2CB', '\x2BB', '\x3', '\x2', '\x2', '\x2', '\x2CB', '\x2BF', - '\x3', '\x2', '\x2', '\x2', '\x2CC', '\x2CD', '\x3', '\x2', '\x2', '\x2', - '\x2CD', '\x2CE', '\b', 'm', '\x3', '\x2', '\x2CE', '\xDA', '\x3', '\x2', - '\x2', '\x2', '\x2CF', '\x2D3', '\a', '%', '\x2', '\x2', '\x2D0', '\x2D2', - '\n', '!', '\x2', '\x2', '\x2D1', '\x2D0', '\x3', '\x2', '\x2', '\x2', - '\x2D2', '\x2D5', '\x3', '\x2', '\x2', '\x2', '\x2D3', '\x2D1', '\x3', - '\x2', '\x2', '\x2', '\x2D3', '\x2D4', '\x3', '\x2', '\x2', '\x2', '\x2D4', - '\x2D6', '\x3', '\x2', '\x2', '\x2', '\x2D5', '\x2D3', '\x3', '\x2', '\x2', - '\x2', '\x2D6', '\x2D7', '\b', 'n', '\x3', '\x2', '\x2D7', '\xDC', '\x3', - '\x2', '\x2', '\x2', '\x2D8', '\x2E2', '\x5', '\xDF', 'p', '\x2', '\x2D9', - '\x2DD', '\t', '\"', '\x2', '\x2', '\x2DA', '\x2DC', '\n', '!', '\x2', - '\x2', '\x2DB', '\x2DA', '\x3', '\x2', '\x2', '\x2', '\x2DC', '\x2DF', - '\x3', '\x2', '\x2', '\x2', '\x2DD', '\x2DB', '\x3', '\x2', '\x2', '\x2', - '\x2DD', '\x2DE', '\x3', '\x2', '\x2', '\x2', '\x2DE', '\x2E3', '\x3', - '\x2', '\x2', '\x2', '\x2DF', '\x2DD', '\x3', '\x2', '\x2', '\x2', '\x2E0', - '\x2E3', '\x5', '\xE1', 'q', '\x2', '\x2E1', '\x2E3', '\a', '\x2', '\x2', - '\x3', '\x2E2', '\x2D9', '\x3', '\x2', '\x2', '\x2', '\x2E2', '\x2E0', - '\x3', '\x2', '\x2', '\x2', '\x2E2', '\x2E1', '\x3', '\x2', '\x2', '\x2', - '\x2E3', '\x2E4', '\x3', '\x2', '\x2', '\x2', '\x2E4', '\x2E5', '\b', - 'o', '\x3', '\x2', '\x2E5', '\xDE', '\x3', '\x2', '\x2', '\x2', '\x2E6', - '\x2E7', '\a', '/', '\x2', '\x2', '\x2E7', '\x2E8', '\a', '/', '\x2', - '\x2', '\x2E8', '\xE0', '\x3', '\x2', '\x2', '\x2', '\x2E9', '\x2EA', - '\t', '!', '\x2', '\x2', '\x2EA', '\xE2', '\x3', '\x2', '\x2', '\x2', - '\x2EB', '\x2EF', '\x5', '\x37', '\x1C', '\x2', '\x2EC', '\x2EF', '\t', - '#', '\x2', '\x2', '\x2ED', '\x2EF', '\x5', '\xB7', '\\', '\x2', '\x2EE', - '\x2EB', '\x3', '\x2', '\x2', '\x2', '\x2EE', '\x2EC', '\x3', '\x2', '\x2', - '\x2', '\x2EE', '\x2ED', '\x3', '\x2', '\x2', '\x2', '\x2EF', '\x2F0', - '\x3', '\x2', '\x2', '\x2', '\x2F0', '\x2EE', '\x3', '\x2', '\x2', '\x2', - '\x2F0', '\x2F1', '\x3', '\x2', '\x2', '\x2', '\x2F1', '\xE4', '\x3', - '\x2', '\x2', '\x2', '\x2F2', '\x2F3', '\a', '\x31', '\x2', '\x2', '\x2F3', - '\x2F4', '\a', ',', '\x2', '\x2', '\x2F4', '\xE6', '\x3', '\x2', '\x2', - '\x2', '\x2F5', '\x2F6', '\a', ',', '\x2', '\x2', '\x2F6', '\x2F7', '\a', - '\x31', '\x2', '\x2', '\x2F7', '\xE8', '\x3', '\x2', '\x2', '\x2', '\x2F8', - '\x2FB', '\x5', '\x37', '\x1C', '\x2', '\x2F9', '\x2FB', '\x5', '\xEB', - 'v', '\x2', '\x2FA', '\x2F8', '\x3', '\x2', '\x2', '\x2', '\x2FA', '\x2F9', - '\x3', '\x2', '\x2', '\x2', '\x2FB', '\xEA', '\x3', '\x2', '\x2', '\x2', - '\x2FC', '\x2FD', '\t', '$', '\x2', '\x2', '\x2FD', '\xEC', '\x3', '\x2', - '\x2', '\x2', '\x2FE', '\x2FF', '\t', '%', '\x2', '\x2', '\x2FF', '\xEE', - '\x3', '\x2', '\x2', '\x2', '#', '\x2', '\x128', '\x132', '\x13A', '\x13E', - '\x146', '\x14E', '\x151', '\x156', '\x15C', '\x15F', '\x165', '\x270', - '\x277', '\x27A', '\x27F', '\x285', '\x28C', '\x28F', '\x29D', '\x2A2', - '\x2A9', '\x2AD', '\x2B2', '\x2B9', '\x2C6', '\x2CB', '\x2D3', '\x2DD', - '\x2E2', '\x2EE', '\x2F0', '\x2FA', '\x4', '\t', '\x30', '\x2', '\x2', + '\x2', '\x2', '\x2', '\x28D', '\x297', '\x3', '\x2', '\x2', '\x2', '\x28E', + '\x28C', '\x3', '\x2', '\x2', '\x2', '\x28F', '\x293', '\x5', '\xED', + 'w', '\x2', '\x290', '\x292', '\x5', '\xEB', 'v', '\x2', '\x291', '\x290', + '\x3', '\x2', '\x2', '\x2', '\x292', '\x295', '\x3', '\x2', '\x2', '\x2', + '\x293', '\x291', '\x3', '\x2', '\x2', '\x2', '\x293', '\x294', '\x3', + '\x2', '\x2', '\x2', '\x294', '\x297', '\x3', '\x2', '\x2', '\x2', '\x295', + '\x293', '\x3', '\x2', '\x2', '\x2', '\x296', '\x275', '\x3', '\x2', '\x2', + '\x2', '\x296', '\x284', '\x3', '\x2', '\x2', '\x2', '\x296', '\x28F', + '\x3', '\x2', '\x2', '\x2', '\x297', '\xCE', '\x3', '\x2', '\x2', '\x2', + '\x298', '\x299', '\t', '\xF', '\x2', '\x2', '\x299', '\x29A', '\x5', + '\xD9', 'm', '\x2', '\x29A', '\xD0', '\x3', '\x2', '\x2', '\x2', '\x29B', + '\x29C', '\a', '\x62', '\x2', '\x2', '\x29C', '\xD2', '\x3', '\x2', '\x2', + '\x2', '\x29D', '\x29E', '\a', ')', '\x2', '\x2', '\x29E', '\xD4', '\x3', + '\x2', '\x2', '\x2', '\x29F', '\x2A0', '\a', '$', '\x2', '\x2', '\x2A0', + '\xD6', '\x3', '\x2', '\x2', '\x2', '\x2A1', '\x2A9', '\x5', '\xD5', 'k', + '\x2', '\x2A2', '\x2A3', '\a', '^', '\x2', '\x2', '\x2A3', '\x2A5', '\v', + '\x2', '\x2', '\x2', '\x2A4', '\x2A2', '\x3', '\x2', '\x2', '\x2', '\x2A4', + '\x2A5', '\x3', '\x2', '\x2', '\x2', '\x2A5', '\x2A6', '\x3', '\x2', '\x2', + '\x2', '\x2A6', '\x2A8', '\v', '\x2', '\x2', '\x2', '\x2A7', '\x2A4', + '\x3', '\x2', '\x2', '\x2', '\x2A8', '\x2AB', '\x3', '\x2', '\x2', '\x2', + '\x2A9', '\x2AA', '\x3', '\x2', '\x2', '\x2', '\x2A9', '\x2A7', '\x3', + '\x2', '\x2', '\x2', '\x2AA', '\x2AC', '\x3', '\x2', '\x2', '\x2', '\x2AB', + '\x2A9', '\x3', '\x2', '\x2', '\x2', '\x2AC', '\x2AD', '\x5', '\xD5', + 'k', '\x2', '\x2AD', '\x2AF', '\x3', '\x2', '\x2', '\x2', '\x2AE', '\x2A1', + '\x3', '\x2', '\x2', '\x2', '\x2AF', '\x2B0', '\x3', '\x2', '\x2', '\x2', + '\x2B0', '\x2AE', '\x3', '\x2', '\x2', '\x2', '\x2B0', '\x2B1', '\x3', + '\x2', '\x2', '\x2', '\x2B1', '\xD8', '\x3', '\x2', '\x2', '\x2', '\x2B2', + '\x2B9', '\x5', '\xD3', 'j', '\x2', '\x2B3', '\x2B5', '\a', '^', '\x2', + '\x2', '\x2B4', '\x2B3', '\x3', '\x2', '\x2', '\x2', '\x2B4', '\x2B5', + '\x3', '\x2', '\x2', '\x2', '\x2B5', '\x2B6', '\x3', '\x2', '\x2', '\x2', + '\x2B6', '\x2B8', '\v', '\x2', '\x2', '\x2', '\x2B7', '\x2B4', '\x3', + '\x2', '\x2', '\x2', '\x2B8', '\x2BB', '\x3', '\x2', '\x2', '\x2', '\x2B9', + '\x2BA', '\x3', '\x2', '\x2', '\x2', '\x2B9', '\x2B7', '\x3', '\x2', '\x2', + '\x2', '\x2BA', '\x2BC', '\x3', '\x2', '\x2', '\x2', '\x2BB', '\x2B9', + '\x3', '\x2', '\x2', '\x2', '\x2BC', '\x2BD', '\x5', '\xD3', 'j', '\x2', + '\x2BD', '\x2BF', '\x3', '\x2', '\x2', '\x2', '\x2BE', '\x2B2', '\x3', + '\x2', '\x2', '\x2', '\x2BF', '\x2C0', '\x3', '\x2', '\x2', '\x2', '\x2C0', + '\x2BE', '\x3', '\x2', '\x2', '\x2', '\x2C0', '\x2C1', '\x3', '\x2', '\x2', + '\x2', '\x2C1', '\xDA', '\x3', '\x2', '\x2', '\x2', '\x2C2', '\x2C3', + '\a', '\x31', '\x2', '\x2', '\x2C3', '\x2C4', '\a', ',', '\x2', '\x2', + '\x2C4', '\x2C5', '\a', ',', '\x2', '\x2', '\x2C5', '\x2D3', '\a', '\x31', + '\x2', '\x2', '\x2C6', '\x2C7', '\a', '\x31', '\x2', '\x2', '\x2C7', '\x2C8', + '\a', ',', '\x2', '\x2', '\x2C8', '\x2C9', '\x3', '\x2', '\x2', '\x2', + '\x2C9', '\x2CD', '\n', ' ', '\x2', '\x2', '\x2CA', '\x2CC', '\v', '\x2', + '\x2', '\x2', '\x2CB', '\x2CA', '\x3', '\x2', '\x2', '\x2', '\x2CC', '\x2CF', + '\x3', '\x2', '\x2', '\x2', '\x2CD', '\x2CE', '\x3', '\x2', '\x2', '\x2', + '\x2CD', '\x2CB', '\x3', '\x2', '\x2', '\x2', '\x2CE', '\x2D0', '\x3', + '\x2', '\x2', '\x2', '\x2CF', '\x2CD', '\x3', '\x2', '\x2', '\x2', '\x2D0', + '\x2D1', '\a', ',', '\x2', '\x2', '\x2D1', '\x2D3', '\a', '\x31', '\x2', + '\x2', '\x2D2', '\x2C2', '\x3', '\x2', '\x2', '\x2', '\x2D2', '\x2C6', + '\x3', '\x2', '\x2', '\x2', '\x2D3', '\x2D4', '\x3', '\x2', '\x2', '\x2', + '\x2D4', '\x2D5', '\b', 'n', '\x3', '\x2', '\x2D5', '\xDC', '\x3', '\x2', + '\x2', '\x2', '\x2D6', '\x2DA', '\a', '%', '\x2', '\x2', '\x2D7', '\x2D9', + '\n', '!', '\x2', '\x2', '\x2D8', '\x2D7', '\x3', '\x2', '\x2', '\x2', + '\x2D9', '\x2DC', '\x3', '\x2', '\x2', '\x2', '\x2DA', '\x2D8', '\x3', + '\x2', '\x2', '\x2', '\x2DA', '\x2DB', '\x3', '\x2', '\x2', '\x2', '\x2DB', + '\x2DD', '\x3', '\x2', '\x2', '\x2', '\x2DC', '\x2DA', '\x3', '\x2', '\x2', + '\x2', '\x2DD', '\x2DE', '\b', 'o', '\x3', '\x2', '\x2DE', '\xDE', '\x3', + '\x2', '\x2', '\x2', '\x2DF', '\x2E9', '\x5', '\xE1', 'q', '\x2', '\x2E0', + '\x2E4', '\t', '\"', '\x2', '\x2', '\x2E1', '\x2E3', '\n', '!', '\x2', + '\x2', '\x2E2', '\x2E1', '\x3', '\x2', '\x2', '\x2', '\x2E3', '\x2E6', + '\x3', '\x2', '\x2', '\x2', '\x2E4', '\x2E2', '\x3', '\x2', '\x2', '\x2', + '\x2E4', '\x2E5', '\x3', '\x2', '\x2', '\x2', '\x2E5', '\x2EA', '\x3', + '\x2', '\x2', '\x2', '\x2E6', '\x2E4', '\x3', '\x2', '\x2', '\x2', '\x2E7', + '\x2EA', '\x5', '\xE3', 'r', '\x2', '\x2E8', '\x2EA', '\a', '\x2', '\x2', + '\x3', '\x2E9', '\x2E0', '\x3', '\x2', '\x2', '\x2', '\x2E9', '\x2E7', + '\x3', '\x2', '\x2', '\x2', '\x2E9', '\x2E8', '\x3', '\x2', '\x2', '\x2', + '\x2EA', '\x2EB', '\x3', '\x2', '\x2', '\x2', '\x2EB', '\x2EC', '\b', + 'p', '\x3', '\x2', '\x2EC', '\xE0', '\x3', '\x2', '\x2', '\x2', '\x2ED', + '\x2EE', '\a', '/', '\x2', '\x2', '\x2EE', '\x2EF', '\a', '/', '\x2', + '\x2', '\x2EF', '\xE2', '\x3', '\x2', '\x2', '\x2', '\x2F0', '\x2F1', + '\t', '!', '\x2', '\x2', '\x2F1', '\xE4', '\x3', '\x2', '\x2', '\x2', + '\x2F2', '\x2F6', '\x5', '\x37', '\x1C', '\x2', '\x2F3', '\x2F6', '\t', + '#', '\x2', '\x2', '\x2F4', '\x2F6', '\x5', '\xB9', ']', '\x2', '\x2F5', + '\x2F2', '\x3', '\x2', '\x2', '\x2', '\x2F5', '\x2F3', '\x3', '\x2', '\x2', + '\x2', '\x2F5', '\x2F4', '\x3', '\x2', '\x2', '\x2', '\x2F6', '\x2F7', + '\x3', '\x2', '\x2', '\x2', '\x2F7', '\x2F5', '\x3', '\x2', '\x2', '\x2', + '\x2F7', '\x2F8', '\x3', '\x2', '\x2', '\x2', '\x2F8', '\xE6', '\x3', + '\x2', '\x2', '\x2', '\x2F9', '\x2FA', '\a', '\x31', '\x2', '\x2', '\x2FA', + '\x2FB', '\a', ',', '\x2', '\x2', '\x2FB', '\xE8', '\x3', '\x2', '\x2', + '\x2', '\x2FC', '\x2FD', '\a', ',', '\x2', '\x2', '\x2FD', '\x2FE', '\a', + '\x31', '\x2', '\x2', '\x2FE', '\xEA', '\x3', '\x2', '\x2', '\x2', '\x2FF', + '\x302', '\x5', '\x37', '\x1C', '\x2', '\x300', '\x302', '\x5', '\xED', + 'w', '\x2', '\x301', '\x2FF', '\x3', '\x2', '\x2', '\x2', '\x301', '\x300', + '\x3', '\x2', '\x2', '\x2', '\x302', '\xEC', '\x3', '\x2', '\x2', '\x2', + '\x303', '\x304', '\t', '$', '\x2', '\x2', '\x304', '\xEE', '\x3', '\x2', + '\x2', '\x2', '\x305', '\x306', '\t', '%', '\x2', '\x2', '\x306', '\xF0', + '\x3', '\x2', '\x2', '\x2', '#', '\x2', '\x12A', '\x134', '\x13C', '\x140', + '\x148', '\x150', '\x153', '\x158', '\x15E', '\x161', '\x167', '\x277', + '\x27E', '\x281', '\x286', '\x28C', '\x293', '\x296', '\x2A4', '\x2A9', + '\x2B0', '\x2B4', '\x2B9', '\x2C0', '\x2CD', '\x2D2', '\x2DA', '\x2E4', + '\x2E9', '\x2F5', '\x2F7', '\x301', '\x4', '\t', '\x31', '\x2', '\x2', '\x3', '\x2', }; diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.interp b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.interp index 16f5c5f..edfe2c4 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.interp +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.interp @@ -38,6 +38,7 @@ null null null null +null '=' ':=' '<=>' @@ -86,6 +87,7 @@ BIN_NUMBER INT_NUMBER DECIMAL_NUMBER FLOAT_NUMBER +SHOW_SYMBOL EXECFILE_SYMBOL QUIT_SYMBOL AND_SYMBOL @@ -195,6 +197,7 @@ BIN_NUMBER INT_NUMBER DECIMAL_NUMBER FLOAT_NUMBER +SHOW_SYMBOL EXECFILE_SYMBOL QUIT_SYMBOL AND_SYMBOL @@ -288,4 +291,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 80, 768, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 6, 29, 295, 10, 29, 13, 29, 14, 29, 296, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 6, 31, 305, 10, 31, 13, 31, 14, 31, 306, 3, 31, 3, 31, 3, 31, 3, 31, 6, 31, 313, 10, 31, 13, 31, 14, 31, 314, 3, 31, 3, 31, 5, 31, 319, 10, 31, 3, 32, 3, 32, 3, 32, 3, 32, 6, 32, 325, 10, 32, 13, 32, 14, 32, 326, 3, 32, 3, 32, 3, 32, 3, 32, 6, 32, 333, 10, 32, 13, 32, 14, 32, 334, 3, 32, 5, 32, 338, 10, 32, 3, 33, 3, 33, 3, 34, 5, 34, 343, 10, 34, 3, 34, 3, 34, 3, 34, 3, 35, 5, 35, 349, 10, 35, 3, 35, 5, 35, 352, 10, 35, 3, 35, 3, 35, 3, 35, 3, 35, 5, 35, 358, 10, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 79, 3, 79, 3, 80, 3, 80, 3, 81, 3, 81, 3, 82, 3, 82, 3, 83, 3, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 101, 3, 101, 3, 102, 6, 102, 623, 10, 102, 13, 102, 14, 102, 624, 3, 102, 3, 102, 3, 102, 7, 102, 630, 10, 102, 12, 102, 14, 102, 633, 11, 102, 5, 102, 635, 10, 102, 3, 102, 6, 102, 638, 10, 102, 13, 102, 14, 102, 639, 3, 102, 3, 102, 7, 102, 644, 10, 102, 12, 102, 14, 102, 647, 11, 102, 3, 102, 3, 102, 7, 102, 651, 10, 102, 12, 102, 14, 102, 654, 11, 102, 5, 102, 656, 10, 102, 3, 103, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 107, 5, 107, 670, 10, 107, 3, 107, 7, 107, 673, 10, 107, 12, 107, 14, 107, 676, 11, 107, 3, 107, 3, 107, 6, 107, 680, 10, 107, 13, 107, 14, 107, 681, 3, 108, 3, 108, 5, 108, 686, 10, 108, 3, 108, 7, 108, 689, 10, 108, 12, 108, 14, 108, 692, 11, 108, 3, 108, 3, 108, 6, 108, 696, 10, 108, 13, 108, 14, 108, 697, 3, 109, 3, 109, 3, 109, 3, 109, 3, 109, 3, 109, 3, 109, 3, 109, 3, 109, 7, 109, 709, 10, 109, 12, 109, 14, 109, 712, 11, 109, 3, 109, 3, 109, 5, 109, 716, 10, 109, 3, 109, 3, 109, 3, 110, 3, 110, 7, 110, 722, 10, 110, 12, 110, 14, 110, 725, 11, 110, 3, 110, 3, 110, 3, 111, 3, 111, 3, 111, 7, 111, 732, 10, 111, 12, 111, 14, 111, 735, 11, 111, 3, 111, 3, 111, 5, 111, 739, 10, 111, 3, 111, 3, 111, 3, 112, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 3, 114, 6, 114, 751, 10, 114, 13, 114, 14, 114, 752, 3, 115, 3, 115, 3, 115, 3, 116, 3, 116, 3, 116, 3, 117, 3, 117, 5, 117, 763, 10, 117, 3, 118, 3, 118, 3, 119, 3, 119, 5, 674, 690, 710, 2, 120, 3, 2, 5, 2, 7, 2, 9, 2, 11, 2, 13, 2, 15, 2, 17, 2, 19, 2, 21, 2, 23, 2, 25, 2, 27, 2, 29, 2, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 2, 55, 2, 57, 2, 59, 2, 61, 3, 63, 4, 65, 5, 67, 6, 69, 7, 71, 8, 73, 9, 75, 10, 77, 11, 79, 12, 81, 13, 83, 14, 85, 15, 87, 16, 89, 17, 91, 18, 93, 19, 95, 20, 97, 21, 99, 22, 101, 23, 103, 24, 105, 25, 107, 26, 109, 27, 111, 28, 113, 29, 115, 30, 117, 31, 119, 32, 121, 33, 123, 34, 125, 35, 127, 36, 129, 37, 131, 38, 133, 39, 135, 40, 137, 41, 139, 42, 141, 43, 143, 44, 145, 45, 147, 46, 149, 47, 151, 48, 153, 80, 155, 49, 157, 50, 159, 51, 161, 52, 163, 53, 165, 54, 167, 55, 169, 56, 171, 57, 173, 58, 175, 59, 177, 60, 179, 61, 181, 62, 183, 63, 185, 64, 187, 65, 189, 66, 191, 67, 193, 68, 195, 69, 197, 70, 199, 71, 201, 72, 203, 73, 205, 74, 207, 2, 209, 2, 211, 2, 213, 75, 215, 76, 217, 77, 219, 78, 221, 79, 223, 2, 225, 2, 227, 2, 229, 2, 231, 2, 233, 2, 235, 2, 237, 2, 3, 2, 38, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 71, 71, 103, 103, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 3, 2, 50, 59, 5, 2, 50, 59, 67, 72, 99, 104, 3, 2, 50, 51, 5, 2, 11, 12, 14, 15, 34, 34, 3, 2, 35, 35, 4, 2, 12, 12, 15, 15, 4, 2, 11, 11, 34, 34, 6, 2, 38, 38, 67, 92, 97, 97, 99, 124, 7, 2, 38, 38, 67, 92, 97, 97, 99, 124, 130, 1, 9, 2, 38, 38, 67, 70, 72, 92, 97, 97, 99, 102, 104, 124, 130, 1, 2, 763, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2, 2, 2, 99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3, 2, 2, 2, 2, 107, 3, 2, 2, 2, 2, 109, 3, 2, 2, 2, 2, 111, 3, 2, 2, 2, 2, 113, 3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2, 2, 2, 2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127, 3, 2, 2, 2, 2, 129, 3, 2, 2, 2, 2, 131, 3, 2, 2, 2, 2, 133, 3, 2, 2, 2, 2, 135, 3, 2, 2, 2, 2, 137, 3, 2, 2, 2, 2, 139, 3, 2, 2, 2, 2, 141, 3, 2, 2, 2, 2, 143, 3, 2, 2, 2, 2, 145, 3, 2, 2, 2, 2, 147, 3, 2, 2, 2, 2, 149, 3, 2, 2, 2, 2, 151, 3, 2, 2, 2, 2, 153, 3, 2, 2, 2, 2, 155, 3, 2, 2, 2, 2, 157, 3, 2, 2, 2, 2, 159, 3, 2, 2, 2, 2, 161, 3, 2, 2, 2, 2, 163, 3, 2, 2, 2, 2, 165, 3, 2, 2, 2, 2, 167, 3, 2, 2, 2, 2, 169, 3, 2, 2, 2, 2, 171, 3, 2, 2, 2, 2, 173, 3, 2, 2, 2, 2, 175, 3, 2, 2, 2, 2, 177, 3, 2, 2, 2, 2, 179, 3, 2, 2, 2, 2, 181, 3, 2, 2, 2, 2, 183, 3, 2, 2, 2, 2, 185, 3, 2, 2, 2, 2, 187, 3, 2, 2, 2, 2, 189, 3, 2, 2, 2, 2, 191, 3, 2, 2, 2, 2, 193, 3, 2, 2, 2, 2, 195, 3, 2, 2, 2, 2, 197, 3, 2, 2, 2, 2, 199, 3, 2, 2, 2, 2, 201, 3, 2, 2, 2, 2, 203, 3, 2, 2, 2, 2, 205, 3, 2, 2, 2, 2, 213, 3, 2, 2, 2, 2, 215, 3, 2, 2, 2, 2, 217, 3, 2, 2, 2, 2, 219, 3, 2, 2, 2, 2, 221, 3, 2, 2, 2, 3, 239, 3, 2, 2, 2, 5, 241, 3, 2, 2, 2, 7, 243, 3, 2, 2, 2, 9, 245, 3, 2, 2, 2, 11, 247, 3, 2, 2, 2, 13, 249, 3, 2, 2, 2, 15, 251, 3, 2, 2, 2, 17, 253, 3, 2, 2, 2, 19, 255, 3, 2, 2, 2, 21, 257, 3, 2, 2, 2, 23, 259, 3, 2, 2, 2, 25, 261, 3, 2, 2, 2, 27, 263, 3, 2, 2, 2, 29, 265, 3, 2, 2, 2, 31, 267, 3, 2, 2, 2, 33, 269, 3, 2, 2, 2, 35, 271, 3, 2, 2, 2, 37, 273, 3, 2, 2, 2, 39, 275, 3, 2, 2, 2, 41, 277, 3, 2, 2, 2, 43, 279, 3, 2, 2, 2, 45, 281, 3, 2, 2, 2, 47, 283, 3, 2, 2, 2, 49, 285, 3, 2, 2, 2, 51, 287, 3, 2, 2, 2, 53, 289, 3, 2, 2, 2, 55, 291, 3, 2, 2, 2, 57, 294, 3, 2, 2, 2, 59, 298, 3, 2, 2, 2, 61, 318, 3, 2, 2, 2, 63, 337, 3, 2, 2, 2, 65, 339, 3, 2, 2, 2, 67, 342, 3, 2, 2, 2, 69, 351, 3, 2, 2, 2, 71, 361, 3, 2, 2, 2, 73, 370, 3, 2, 2, 2, 75, 375, 3, 2, 2, 2, 77, 379, 3, 2, 2, 2, 79, 383, 3, 2, 2, 2, 81, 386, 3, 2, 2, 2, 83, 392, 3, 2, 2, 2, 85, 395, 3, 2, 2, 2, 87, 400, 3, 2, 2, 2, 89, 407, 3, 2, 2, 2, 91, 414, 3, 2, 2, 2, 93, 419, 3, 2, 2, 2, 95, 424, 3, 2, 2, 2, 97, 430, 3, 2, 2, 2, 99, 435, 3, 2, 2, 2, 101, 441, 3, 2, 2, 2, 103, 448, 3, 2, 2, 2, 105, 453, 3, 2, 2, 2, 107, 457, 3, 2, 2, 2, 109, 461, 3, 2, 2, 2, 111, 465, 3, 2, 2, 2, 113, 468, 3, 2, 2, 2, 115, 474, 3, 2, 2, 2, 117, 477, 3, 2, 2, 2, 119, 485, 3, 2, 2, 2, 121, 492, 3, 2, 2, 2, 123, 499, 3, 2, 2, 2, 125, 505, 3, 2, 2, 2, 127, 512, 3, 2, 2, 2, 129, 519, 3, 2, 2, 2, 131, 525, 3, 2, 2, 2, 133, 531, 3, 2, 2, 2, 135, 536, 3, 2, 2, 2, 137, 540, 3, 2, 2, 2, 139, 542, 3, 2, 2, 2, 141, 545, 3, 2, 2, 2, 143, 549, 3, 2, 2, 2, 145, 552, 3, 2, 2, 2, 147, 554, 3, 2, 2, 2, 149, 557, 3, 2, 2, 2, 151, 559, 3, 2, 2, 2, 153, 562, 3, 2, 2, 2, 155, 567, 3, 2, 2, 2, 157, 569, 3, 2, 2, 2, 159, 571, 3, 2, 2, 2, 161, 573, 3, 2, 2, 2, 163, 575, 3, 2, 2, 2, 165, 577, 3, 2, 2, 2, 167, 579, 3, 2, 2, 2, 169, 581, 3, 2, 2, 2, 171, 584, 3, 2, 2, 2, 173, 587, 3, 2, 2, 2, 175, 590, 3, 2, 2, 2, 177, 592, 3, 2, 2, 2, 179, 594, 3, 2, 2, 2, 181, 597, 3, 2, 2, 2, 183, 599, 3, 2, 2, 2, 185, 601, 3, 2, 2, 2, 187, 603, 3, 2, 2, 2, 189, 605, 3, 2, 2, 2, 191, 607, 3, 2, 2, 2, 193, 609, 3, 2, 2, 2, 195, 611, 3, 2, 2, 2, 197, 613, 3, 2, 2, 2, 199, 615, 3, 2, 2, 2, 201, 617, 3, 2, 2, 2, 203, 655, 3, 2, 2, 2, 205, 657, 3, 2, 2, 2, 207, 660, 3, 2, 2, 2, 209, 662, 3, 2, 2, 2, 211, 664, 3, 2, 2, 2, 213, 679, 3, 2, 2, 2, 215, 695, 3, 2, 2, 2, 217, 715, 3, 2, 2, 2, 219, 719, 3, 2, 2, 2, 221, 728, 3, 2, 2, 2, 223, 742, 3, 2, 2, 2, 225, 745, 3, 2, 2, 2, 227, 750, 3, 2, 2, 2, 229, 754, 3, 2, 2, 2, 231, 757, 3, 2, 2, 2, 233, 762, 3, 2, 2, 2, 235, 764, 3, 2, 2, 2, 237, 766, 3, 2, 2, 2, 239, 240, 9, 2, 2, 2, 240, 4, 3, 2, 2, 2, 241, 242, 9, 3, 2, 2, 242, 6, 3, 2, 2, 2, 243, 244, 9, 4, 2, 2, 244, 8, 3, 2, 2, 2, 245, 246, 9, 5, 2, 2, 246, 10, 3, 2, 2, 2, 247, 248, 9, 6, 2, 2, 248, 12, 3, 2, 2, 2, 249, 250, 9, 7, 2, 2, 250, 14, 3, 2, 2, 2, 251, 252, 9, 8, 2, 2, 252, 16, 3, 2, 2, 2, 253, 254, 9, 9, 2, 2, 254, 18, 3, 2, 2, 2, 255, 256, 9, 10, 2, 2, 256, 20, 3, 2, 2, 2, 257, 258, 9, 11, 2, 2, 258, 22, 3, 2, 2, 2, 259, 260, 9, 12, 2, 2, 260, 24, 3, 2, 2, 2, 261, 262, 9, 13, 2, 2, 262, 26, 3, 2, 2, 2, 263, 264, 9, 14, 2, 2, 264, 28, 3, 2, 2, 2, 265, 266, 9, 15, 2, 2, 266, 30, 3, 2, 2, 2, 267, 268, 9, 16, 2, 2, 268, 32, 3, 2, 2, 2, 269, 270, 9, 17, 2, 2, 270, 34, 3, 2, 2, 2, 271, 272, 9, 18, 2, 2, 272, 36, 3, 2, 2, 2, 273, 274, 9, 19, 2, 2, 274, 38, 3, 2, 2, 2, 275, 276, 9, 20, 2, 2, 276, 40, 3, 2, 2, 2, 277, 278, 9, 21, 2, 2, 278, 42, 3, 2, 2, 2, 279, 280, 9, 22, 2, 2, 280, 44, 3, 2, 2, 2, 281, 282, 9, 23, 2, 2, 282, 46, 3, 2, 2, 2, 283, 284, 9, 24, 2, 2, 284, 48, 3, 2, 2, 2, 285, 286, 9, 25, 2, 2, 286, 50, 3, 2, 2, 2, 287, 288, 9, 26, 2, 2, 288, 52, 3, 2, 2, 2, 289, 290, 9, 27, 2, 2, 290, 54, 3, 2, 2, 2, 291, 292, 9, 28, 2, 2, 292, 56, 3, 2, 2, 2, 293, 295, 5, 55, 28, 2, 294, 293, 3, 2, 2, 2, 295, 296, 3, 2, 2, 2, 296, 294, 3, 2, 2, 2, 296, 297, 3, 2, 2, 2, 297, 58, 3, 2, 2, 2, 298, 299, 9, 29, 2, 2, 299, 60, 3, 2, 2, 2, 300, 301, 7, 50, 2, 2, 301, 302, 7, 122, 2, 2, 302, 304, 3, 2, 2, 2, 303, 305, 5, 59, 30, 2, 304, 303, 3, 2, 2, 2, 305, 306, 3, 2, 2, 2, 306, 304, 3, 2, 2, 2, 306, 307, 3, 2, 2, 2, 307, 319, 3, 2, 2, 2, 308, 309, 7, 122, 2, 2, 309, 310, 7, 41, 2, 2, 310, 312, 3, 2, 2, 2, 311, 313, 5, 59, 30, 2, 312, 311, 3, 2, 2, 2, 313, 314, 3, 2, 2, 2, 314, 312, 3, 2, 2, 2, 314, 315, 3, 2, 2, 2, 315, 316, 3, 2, 2, 2, 316, 317, 7, 41, 2, 2, 317, 319, 3, 2, 2, 2, 318, 300, 3, 2, 2, 2, 318, 308, 3, 2, 2, 2, 319, 62, 3, 2, 2, 2, 320, 321, 7, 50, 2, 2, 321, 322, 7, 100, 2, 2, 322, 324, 3, 2, 2, 2, 323, 325, 9, 30, 2, 2, 324, 323, 3, 2, 2, 2, 325, 326, 3, 2, 2, 2, 326, 324, 3, 2, 2, 2, 326, 327, 3, 2, 2, 2, 327, 338, 3, 2, 2, 2, 328, 329, 7, 100, 2, 2, 329, 330, 7, 41, 2, 2, 330, 332, 3, 2, 2, 2, 331, 333, 9, 30, 2, 2, 332, 331, 3, 2, 2, 2, 333, 334, 3, 2, 2, 2, 334, 332, 3, 2, 2, 2, 334, 335, 3, 2, 2, 2, 335, 336, 3, 2, 2, 2, 336, 338, 7, 41, 2, 2, 337, 320, 3, 2, 2, 2, 337, 328, 3, 2, 2, 2, 338, 64, 3, 2, 2, 2, 339, 340, 5, 57, 29, 2, 340, 66, 3, 2, 2, 2, 341, 343, 5, 57, 29, 2, 342, 341, 3, 2, 2, 2, 342, 343, 3, 2, 2, 2, 343, 344, 3, 2, 2, 2, 344, 345, 5, 183, 92, 2, 345, 346, 5, 57, 29, 2, 346, 68, 3, 2, 2, 2, 347, 349, 5, 57, 29, 2, 348, 347, 3, 2, 2, 2, 348, 349, 3, 2, 2, 2, 349, 350, 3, 2, 2, 2, 350, 352, 5, 183, 92, 2, 351, 348, 3, 2, 2, 2, 351, 352, 3, 2, 2, 2, 352, 353, 3, 2, 2, 2, 353, 354, 5, 57, 29, 2, 354, 357, 9, 6, 2, 2, 355, 358, 5, 157, 79, 2, 356, 358, 5, 155, 78, 2, 357, 355, 3, 2, 2, 2, 357, 356, 3, 2, 2, 2, 357, 358, 3, 2, 2, 2, 358, 359, 3, 2, 2, 2, 359, 360, 5, 57, 29, 2, 360, 70, 3, 2, 2, 2, 361, 362, 5, 11, 6, 2, 362, 363, 5, 49, 25, 2, 363, 364, 5, 11, 6, 2, 364, 365, 5, 7, 4, 2, 365, 366, 5, 13, 7, 2, 366, 367, 5, 19, 10, 2, 367, 368, 5, 25, 13, 2, 368, 369, 5, 11, 6, 2, 369, 72, 3, 2, 2, 2, 370, 371, 5, 35, 18, 2, 371, 372, 5, 43, 22, 2, 372, 373, 5, 19, 10, 2, 373, 374, 5, 41, 21, 2, 374, 74, 3, 2, 2, 2, 375, 376, 5, 3, 2, 2, 376, 377, 5, 29, 15, 2, 377, 378, 5, 9, 5, 2, 378, 76, 3, 2, 2, 2, 379, 380, 5, 3, 2, 2, 380, 381, 5, 39, 20, 2, 381, 382, 5, 7, 4, 2, 382, 78, 3, 2, 2, 2, 383, 384, 5, 3, 2, 2, 384, 385, 5, 39, 20, 2, 385, 80, 3, 2, 2, 2, 386, 387, 5, 5, 3, 2, 387, 388, 5, 11, 6, 2, 388, 389, 5, 15, 8, 2, 389, 390, 5, 19, 10, 2, 390, 391, 5, 29, 15, 2, 391, 82, 3, 2, 2, 2, 392, 393, 5, 5, 3, 2, 393, 394, 5, 51, 26, 2, 394, 84, 3, 2, 2, 2, 395, 396, 5, 7, 4, 2, 396, 397, 5, 17, 9, 2, 397, 398, 5, 3, 2, 2, 398, 399, 5, 37, 19, 2, 399, 86, 3, 2, 2, 2, 400, 401, 5, 7, 4, 2, 401, 402, 5, 37, 19, 2, 402, 403, 5, 11, 6, 2, 403, 404, 5, 3, 2, 2, 404, 405, 5, 41, 21, 2, 405, 406, 5, 11, 6, 2, 406, 88, 3, 2, 2, 2, 407, 408, 5, 9, 5, 2, 408, 409, 5, 11, 6, 2, 409, 410, 5, 25, 13, 2, 410, 411, 5, 11, 6, 2, 411, 412, 5, 41, 21, 2, 412, 413, 5, 11, 6, 2, 413, 90, 3, 2, 2, 2, 414, 415, 5, 9, 5, 2, 415, 416, 5, 11, 6, 2, 416, 417, 5, 39, 20, 2, 417, 418, 5, 7, 4, 2, 418, 92, 3, 2, 2, 2, 419, 420, 5, 9, 5, 2, 420, 421, 5, 37, 19, 2, 421, 422, 5, 31, 16, 2, 422, 423, 5, 33, 17, 2, 423, 94, 3, 2, 2, 2, 424, 425, 5, 13, 7, 2, 425, 426, 5, 25, 13, 2, 426, 427, 5, 31, 16, 2, 427, 428, 5, 3, 2, 2, 428, 429, 5, 41, 21, 2, 429, 96, 3, 2, 2, 2, 430, 431, 5, 13, 7, 2, 431, 432, 5, 37, 19, 2, 432, 433, 5, 31, 16, 2, 433, 434, 5, 27, 14, 2, 434, 98, 3, 2, 2, 2, 435, 436, 5, 19, 10, 2, 436, 437, 5, 29, 15, 2, 437, 438, 5, 9, 5, 2, 438, 439, 5, 11, 6, 2, 439, 440, 5, 49, 25, 2, 440, 100, 3, 2, 2, 2, 441, 442, 5, 19, 10, 2, 442, 443, 5, 29, 15, 2, 443, 444, 5, 39, 20, 2, 444, 445, 5, 11, 6, 2, 445, 446, 5, 37, 19, 2, 446, 447, 5, 41, 21, 2, 447, 102, 3, 2, 2, 2, 448, 449, 5, 19, 10, 2, 449, 450, 5, 29, 15, 2, 450, 451, 5, 41, 21, 2, 451, 452, 5, 31, 16, 2, 452, 104, 3, 2, 2, 2, 453, 454, 5, 19, 10, 2, 454, 455, 5, 29, 15, 2, 455, 456, 5, 41, 21, 2, 456, 106, 3, 2, 2, 2, 457, 458, 5, 23, 12, 2, 458, 459, 5, 11, 6, 2, 459, 460, 5, 51, 26, 2, 460, 108, 3, 2, 2, 2, 461, 462, 5, 29, 15, 2, 462, 463, 5, 31, 16, 2, 463, 464, 5, 41, 21, 2, 464, 110, 3, 2, 2, 2, 465, 466, 5, 31, 16, 2, 466, 467, 5, 29, 15, 2, 467, 112, 3, 2, 2, 2, 468, 469, 5, 31, 16, 2, 469, 470, 5, 37, 19, 2, 470, 471, 5, 9, 5, 2, 471, 472, 5, 11, 6, 2, 472, 473, 5, 37, 19, 2, 473, 114, 3, 2, 2, 2, 474, 475, 5, 31, 16, 2, 475, 476, 5, 37, 19, 2, 476, 116, 3, 2, 2, 2, 477, 478, 5, 33, 17, 2, 478, 479, 5, 37, 19, 2, 479, 480, 5, 19, 10, 2, 480, 481, 5, 27, 14, 2, 481, 482, 5, 3, 2, 2, 482, 483, 5, 37, 19, 2, 483, 484, 5, 51, 26, 2, 484, 118, 3, 2, 2, 2, 485, 486, 5, 39, 20, 2, 486, 487, 5, 11, 6, 2, 487, 488, 5, 25, 13, 2, 488, 489, 5, 11, 6, 2, 489, 490, 5, 7, 4, 2, 490, 491, 5, 41, 21, 2, 491, 120, 3, 2, 2, 2, 492, 493, 5, 41, 21, 2, 493, 494, 5, 3, 2, 2, 494, 495, 5, 5, 3, 2, 495, 496, 5, 25, 13, 2, 496, 497, 5, 11, 6, 2, 497, 498, 5, 39, 20, 2, 498, 122, 3, 2, 2, 2, 499, 500, 5, 41, 21, 2, 500, 501, 5, 3, 2, 2, 501, 502, 5, 5, 3, 2, 502, 503, 5, 25, 13, 2, 503, 504, 5, 11, 6, 2, 504, 124, 3, 2, 2, 2, 505, 506, 5, 43, 22, 2, 506, 507, 5, 29, 15, 2, 507, 508, 5, 19, 10, 2, 508, 509, 5, 35, 18, 2, 509, 510, 5, 43, 22, 2, 510, 511, 5, 11, 6, 2, 511, 126, 3, 2, 2, 2, 512, 513, 5, 45, 23, 2, 513, 514, 5, 3, 2, 2, 514, 515, 5, 25, 13, 2, 515, 516, 5, 43, 22, 2, 516, 517, 5, 11, 6, 2, 517, 518, 5, 39, 20, 2, 518, 128, 3, 2, 2, 2, 519, 520, 5, 45, 23, 2, 520, 521, 5, 3, 2, 2, 521, 522, 5, 25, 13, 2, 522, 523, 5, 43, 22, 2, 523, 524, 5, 11, 6, 2, 524, 130, 3, 2, 2, 2, 525, 526, 5, 47, 24, 2, 526, 527, 5, 17, 9, 2, 527, 528, 5, 11, 6, 2, 528, 529, 5, 37, 19, 2, 529, 530, 5, 11, 6, 2, 530, 132, 3, 2, 2, 2, 531, 532, 5, 47, 24, 2, 532, 533, 5, 31, 16, 2, 533, 534, 5, 37, 19, 2, 534, 535, 5, 23, 12, 2, 535, 134, 3, 2, 2, 2, 536, 537, 5, 49, 25, 2, 537, 538, 5, 31, 16, 2, 538, 539, 5, 37, 19, 2, 539, 136, 3, 2, 2, 2, 540, 541, 7, 63, 2, 2, 541, 138, 3, 2, 2, 2, 542, 543, 7, 60, 2, 2, 543, 544, 7, 63, 2, 2, 544, 140, 3, 2, 2, 2, 545, 546, 7, 62, 2, 2, 546, 547, 7, 63, 2, 2, 547, 548, 7, 64, 2, 2, 548, 142, 3, 2, 2, 2, 549, 550, 7, 64, 2, 2, 550, 551, 7, 63, 2, 2, 551, 144, 3, 2, 2, 2, 552, 553, 7, 64, 2, 2, 553, 146, 3, 2, 2, 2, 554, 555, 7, 62, 2, 2, 555, 556, 7, 63, 2, 2, 556, 148, 3, 2, 2, 2, 557, 558, 7, 62, 2, 2, 558, 150, 3, 2, 2, 2, 559, 560, 7, 35, 2, 2, 560, 561, 7, 63, 2, 2, 561, 152, 3, 2, 2, 2, 562, 563, 7, 62, 2, 2, 563, 564, 7, 64, 2, 2, 564, 565, 3, 2, 2, 2, 565, 566, 8, 77, 2, 2, 566, 154, 3, 2, 2, 2, 567, 568, 7, 45, 2, 2, 568, 156, 3, 2, 2, 2, 569, 570, 7, 47, 2, 2, 570, 158, 3, 2, 2, 2, 571, 572, 7, 44, 2, 2, 572, 160, 3, 2, 2, 2, 573, 574, 7, 49, 2, 2, 574, 162, 3, 2, 2, 2, 575, 576, 7, 39, 2, 2, 576, 164, 3, 2, 2, 2, 577, 578, 7, 35, 2, 2, 578, 166, 3, 2, 2, 2, 579, 580, 7, 128, 2, 2, 580, 168, 3, 2, 2, 2, 581, 582, 7, 62, 2, 2, 582, 583, 7, 62, 2, 2, 583, 170, 3, 2, 2, 2, 584, 585, 7, 64, 2, 2, 585, 586, 7, 64, 2, 2, 586, 172, 3, 2, 2, 2, 587, 588, 7, 40, 2, 2, 588, 589, 7, 40, 2, 2, 589, 174, 3, 2, 2, 2, 590, 591, 7, 40, 2, 2, 591, 176, 3, 2, 2, 2, 592, 593, 7, 96, 2, 2, 593, 178, 3, 2, 2, 2, 594, 595, 7, 126, 2, 2, 595, 596, 7, 126, 2, 2, 596, 180, 3, 2, 2, 2, 597, 598, 7, 126, 2, 2, 598, 182, 3, 2, 2, 2, 599, 600, 7, 48, 2, 2, 600, 184, 3, 2, 2, 2, 601, 602, 7, 46, 2, 2, 602, 186, 3, 2, 2, 2, 603, 604, 7, 61, 2, 2, 604, 188, 3, 2, 2, 2, 605, 606, 7, 60, 2, 2, 606, 190, 3, 2, 2, 2, 607, 608, 7, 42, 2, 2, 608, 192, 3, 2, 2, 2, 609, 610, 7, 43, 2, 2, 610, 194, 3, 2, 2, 2, 611, 612, 7, 125, 2, 2, 612, 196, 3, 2, 2, 2, 613, 614, 7, 127, 2, 2, 614, 198, 3, 2, 2, 2, 615, 616, 7, 97, 2, 2, 616, 200, 3, 2, 2, 2, 617, 618, 9, 31, 2, 2, 618, 619, 3, 2, 2, 2, 619, 620, 8, 101, 3, 2, 620, 202, 3, 2, 2, 2, 621, 623, 5, 57, 29, 2, 622, 621, 3, 2, 2, 2, 623, 624, 3, 2, 2, 2, 624, 622, 3, 2, 2, 2, 624, 625, 3, 2, 2, 2, 625, 626, 3, 2, 2, 2, 626, 634, 9, 6, 2, 2, 627, 631, 5, 235, 118, 2, 628, 630, 5, 233, 117, 2, 629, 628, 3, 2, 2, 2, 630, 633, 3, 2, 2, 2, 631, 629, 3, 2, 2, 2, 631, 632, 3, 2, 2, 2, 632, 635, 3, 2, 2, 2, 633, 631, 3, 2, 2, 2, 634, 627, 3, 2, 2, 2, 634, 635, 3, 2, 2, 2, 635, 656, 3, 2, 2, 2, 636, 638, 5, 57, 29, 2, 637, 636, 3, 2, 2, 2, 638, 639, 3, 2, 2, 2, 639, 637, 3, 2, 2, 2, 639, 640, 3, 2, 2, 2, 640, 641, 3, 2, 2, 2, 641, 645, 5, 237, 119, 2, 642, 644, 5, 233, 117, 2, 643, 642, 3, 2, 2, 2, 644, 647, 3, 2, 2, 2, 645, 643, 3, 2, 2, 2, 645, 646, 3, 2, 2, 2, 646, 656, 3, 2, 2, 2, 647, 645, 3, 2, 2, 2, 648, 652, 5, 235, 118, 2, 649, 651, 5, 233, 117, 2, 650, 649, 3, 2, 2, 2, 651, 654, 3, 2, 2, 2, 652, 650, 3, 2, 2, 2, 652, 653, 3, 2, 2, 2, 653, 656, 3, 2, 2, 2, 654, 652, 3, 2, 2, 2, 655, 622, 3, 2, 2, 2, 655, 637, 3, 2, 2, 2, 655, 648, 3, 2, 2, 2, 656, 204, 3, 2, 2, 2, 657, 658, 9, 15, 2, 2, 658, 659, 5, 215, 108, 2, 659, 206, 3, 2, 2, 2, 660, 661, 7, 98, 2, 2, 661, 208, 3, 2, 2, 2, 662, 663, 7, 41, 2, 2, 663, 210, 3, 2, 2, 2, 664, 665, 7, 36, 2, 2, 665, 212, 3, 2, 2, 2, 666, 674, 5, 211, 106, 2, 667, 668, 7, 94, 2, 2, 668, 670, 11, 2, 2, 2, 669, 667, 3, 2, 2, 2, 669, 670, 3, 2, 2, 2, 670, 671, 3, 2, 2, 2, 671, 673, 11, 2, 2, 2, 672, 669, 3, 2, 2, 2, 673, 676, 3, 2, 2, 2, 674, 675, 3, 2, 2, 2, 674, 672, 3, 2, 2, 2, 675, 677, 3, 2, 2, 2, 676, 674, 3, 2, 2, 2, 677, 678, 5, 211, 106, 2, 678, 680, 3, 2, 2, 2, 679, 666, 3, 2, 2, 2, 680, 681, 3, 2, 2, 2, 681, 679, 3, 2, 2, 2, 681, 682, 3, 2, 2, 2, 682, 214, 3, 2, 2, 2, 683, 690, 5, 209, 105, 2, 684, 686, 7, 94, 2, 2, 685, 684, 3, 2, 2, 2, 685, 686, 3, 2, 2, 2, 686, 687, 3, 2, 2, 2, 687, 689, 11, 2, 2, 2, 688, 685, 3, 2, 2, 2, 689, 692, 3, 2, 2, 2, 690, 691, 3, 2, 2, 2, 690, 688, 3, 2, 2, 2, 691, 693, 3, 2, 2, 2, 692, 690, 3, 2, 2, 2, 693, 694, 5, 209, 105, 2, 694, 696, 3, 2, 2, 2, 695, 683, 3, 2, 2, 2, 696, 697, 3, 2, 2, 2, 697, 695, 3, 2, 2, 2, 697, 698, 3, 2, 2, 2, 698, 216, 3, 2, 2, 2, 699, 700, 7, 49, 2, 2, 700, 701, 7, 44, 2, 2, 701, 702, 7, 44, 2, 2, 702, 716, 7, 49, 2, 2, 703, 704, 7, 49, 2, 2, 704, 705, 7, 44, 2, 2, 705, 706, 3, 2, 2, 2, 706, 710, 10, 32, 2, 2, 707, 709, 11, 2, 2, 2, 708, 707, 3, 2, 2, 2, 709, 712, 3, 2, 2, 2, 710, 711, 3, 2, 2, 2, 710, 708, 3, 2, 2, 2, 711, 713, 3, 2, 2, 2, 712, 710, 3, 2, 2, 2, 713, 714, 7, 44, 2, 2, 714, 716, 7, 49, 2, 2, 715, 699, 3, 2, 2, 2, 715, 703, 3, 2, 2, 2, 716, 717, 3, 2, 2, 2, 717, 718, 8, 109, 3, 2, 718, 218, 3, 2, 2, 2, 719, 723, 7, 37, 2, 2, 720, 722, 10, 33, 2, 2, 721, 720, 3, 2, 2, 2, 722, 725, 3, 2, 2, 2, 723, 721, 3, 2, 2, 2, 723, 724, 3, 2, 2, 2, 724, 726, 3, 2, 2, 2, 725, 723, 3, 2, 2, 2, 726, 727, 8, 110, 3, 2, 727, 220, 3, 2, 2, 2, 728, 738, 5, 223, 112, 2, 729, 733, 9, 34, 2, 2, 730, 732, 10, 33, 2, 2, 731, 730, 3, 2, 2, 2, 732, 735, 3, 2, 2, 2, 733, 731, 3, 2, 2, 2, 733, 734, 3, 2, 2, 2, 734, 739, 3, 2, 2, 2, 735, 733, 3, 2, 2, 2, 736, 739, 5, 225, 113, 2, 737, 739, 7, 2, 2, 3, 738, 729, 3, 2, 2, 2, 738, 736, 3, 2, 2, 2, 738, 737, 3, 2, 2, 2, 739, 740, 3, 2, 2, 2, 740, 741, 8, 111, 3, 2, 741, 222, 3, 2, 2, 2, 742, 743, 7, 47, 2, 2, 743, 744, 7, 47, 2, 2, 744, 224, 3, 2, 2, 2, 745, 746, 9, 33, 2, 2, 746, 226, 3, 2, 2, 2, 747, 751, 5, 55, 28, 2, 748, 751, 9, 35, 2, 2, 749, 751, 5, 183, 92, 2, 750, 747, 3, 2, 2, 2, 750, 748, 3, 2, 2, 2, 750, 749, 3, 2, 2, 2, 751, 752, 3, 2, 2, 2, 752, 750, 3, 2, 2, 2, 752, 753, 3, 2, 2, 2, 753, 228, 3, 2, 2, 2, 754, 755, 7, 49, 2, 2, 755, 756, 7, 44, 2, 2, 756, 230, 3, 2, 2, 2, 757, 758, 7, 44, 2, 2, 758, 759, 7, 49, 2, 2, 759, 232, 3, 2, 2, 2, 760, 763, 5, 55, 28, 2, 761, 763, 5, 235, 118, 2, 762, 760, 3, 2, 2, 2, 762, 761, 3, 2, 2, 2, 763, 234, 3, 2, 2, 2, 764, 765, 9, 36, 2, 2, 765, 236, 3, 2, 2, 2, 766, 767, 9, 37, 2, 2, 767, 238, 3, 2, 2, 2, 35, 2, 296, 306, 314, 318, 326, 334, 337, 342, 348, 351, 357, 624, 631, 634, 639, 645, 652, 655, 669, 674, 681, 685, 690, 697, 710, 715, 723, 733, 738, 750, 752, 762, 4, 9, 48, 2, 2, 3, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 81, 775, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 4, 120, 9, 120, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 6, 29, 297, 10, 29, 13, 29, 14, 29, 298, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 6, 31, 307, 10, 31, 13, 31, 14, 31, 308, 3, 31, 3, 31, 3, 31, 3, 31, 6, 31, 315, 10, 31, 13, 31, 14, 31, 316, 3, 31, 3, 31, 5, 31, 321, 10, 31, 3, 32, 3, 32, 3, 32, 3, 32, 6, 32, 327, 10, 32, 13, 32, 14, 32, 328, 3, 32, 3, 32, 3, 32, 3, 32, 6, 32, 335, 10, 32, 13, 32, 14, 32, 336, 3, 32, 5, 32, 340, 10, 32, 3, 33, 3, 33, 3, 34, 5, 34, 345, 10, 34, 3, 34, 3, 34, 3, 34, 3, 35, 5, 35, 351, 10, 35, 3, 35, 5, 35, 354, 10, 35, 3, 35, 3, 35, 3, 35, 3, 35, 5, 35, 360, 10, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 80, 3, 80, 3, 81, 3, 81, 3, 82, 3, 82, 3, 83, 3, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 102, 3, 102, 3, 103, 6, 103, 630, 10, 103, 13, 103, 14, 103, 631, 3, 103, 3, 103, 3, 103, 7, 103, 637, 10, 103, 12, 103, 14, 103, 640, 11, 103, 5, 103, 642, 10, 103, 3, 103, 6, 103, 645, 10, 103, 13, 103, 14, 103, 646, 3, 103, 3, 103, 7, 103, 651, 10, 103, 12, 103, 14, 103, 654, 11, 103, 3, 103, 3, 103, 7, 103, 658, 10, 103, 12, 103, 14, 103, 661, 11, 103, 5, 103, 663, 10, 103, 3, 104, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 108, 5, 108, 677, 10, 108, 3, 108, 7, 108, 680, 10, 108, 12, 108, 14, 108, 683, 11, 108, 3, 108, 3, 108, 6, 108, 687, 10, 108, 13, 108, 14, 108, 688, 3, 109, 3, 109, 5, 109, 693, 10, 109, 3, 109, 7, 109, 696, 10, 109, 12, 109, 14, 109, 699, 11, 109, 3, 109, 3, 109, 6, 109, 703, 10, 109, 13, 109, 14, 109, 704, 3, 110, 3, 110, 3, 110, 3, 110, 3, 110, 3, 110, 3, 110, 3, 110, 3, 110, 7, 110, 716, 10, 110, 12, 110, 14, 110, 719, 11, 110, 3, 110, 3, 110, 5, 110, 723, 10, 110, 3, 110, 3, 110, 3, 111, 3, 111, 7, 111, 729, 10, 111, 12, 111, 14, 111, 732, 11, 111, 3, 111, 3, 111, 3, 112, 3, 112, 3, 112, 7, 112, 739, 10, 112, 12, 112, 14, 112, 742, 11, 112, 3, 112, 3, 112, 5, 112, 746, 10, 112, 3, 112, 3, 112, 3, 113, 3, 113, 3, 113, 3, 114, 3, 114, 3, 115, 3, 115, 3, 115, 6, 115, 758, 10, 115, 13, 115, 14, 115, 759, 3, 116, 3, 116, 3, 116, 3, 117, 3, 117, 3, 117, 3, 118, 3, 118, 5, 118, 770, 10, 118, 3, 119, 3, 119, 3, 120, 3, 120, 5, 681, 697, 717, 2, 121, 3, 2, 5, 2, 7, 2, 9, 2, 11, 2, 13, 2, 15, 2, 17, 2, 19, 2, 21, 2, 23, 2, 25, 2, 27, 2, 29, 2, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 2, 55, 2, 57, 2, 59, 2, 61, 3, 63, 4, 65, 5, 67, 6, 69, 7, 71, 8, 73, 9, 75, 10, 77, 11, 79, 12, 81, 13, 83, 14, 85, 15, 87, 16, 89, 17, 91, 18, 93, 19, 95, 20, 97, 21, 99, 22, 101, 23, 103, 24, 105, 25, 107, 26, 109, 27, 111, 28, 113, 29, 115, 30, 117, 31, 119, 32, 121, 33, 123, 34, 125, 35, 127, 36, 129, 37, 131, 38, 133, 39, 135, 40, 137, 41, 139, 42, 141, 43, 143, 44, 145, 45, 147, 46, 149, 47, 151, 48, 153, 49, 155, 81, 157, 50, 159, 51, 161, 52, 163, 53, 165, 54, 167, 55, 169, 56, 171, 57, 173, 58, 175, 59, 177, 60, 179, 61, 181, 62, 183, 63, 185, 64, 187, 65, 189, 66, 191, 67, 193, 68, 195, 69, 197, 70, 199, 71, 201, 72, 203, 73, 205, 74, 207, 75, 209, 2, 211, 2, 213, 2, 215, 76, 217, 77, 219, 78, 221, 79, 223, 80, 225, 2, 227, 2, 229, 2, 231, 2, 233, 2, 235, 2, 237, 2, 239, 2, 3, 2, 38, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 71, 71, 103, 103, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 3, 2, 50, 59, 5, 2, 50, 59, 67, 72, 99, 104, 3, 2, 50, 51, 5, 2, 11, 12, 14, 15, 34, 34, 3, 2, 35, 35, 4, 2, 12, 12, 15, 15, 4, 2, 11, 11, 34, 34, 6, 2, 38, 38, 67, 92, 97, 97, 99, 124, 7, 2, 38, 38, 67, 92, 97, 97, 99, 124, 130, 1, 9, 2, 38, 38, 67, 70, 72, 92, 97, 97, 99, 102, 104, 124, 130, 1, 2, 770, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2, 2, 2, 99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3, 2, 2, 2, 2, 107, 3, 2, 2, 2, 2, 109, 3, 2, 2, 2, 2, 111, 3, 2, 2, 2, 2, 113, 3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2, 2, 2, 2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127, 3, 2, 2, 2, 2, 129, 3, 2, 2, 2, 2, 131, 3, 2, 2, 2, 2, 133, 3, 2, 2, 2, 2, 135, 3, 2, 2, 2, 2, 137, 3, 2, 2, 2, 2, 139, 3, 2, 2, 2, 2, 141, 3, 2, 2, 2, 2, 143, 3, 2, 2, 2, 2, 145, 3, 2, 2, 2, 2, 147, 3, 2, 2, 2, 2, 149, 3, 2, 2, 2, 2, 151, 3, 2, 2, 2, 2, 153, 3, 2, 2, 2, 2, 155, 3, 2, 2, 2, 2, 157, 3, 2, 2, 2, 2, 159, 3, 2, 2, 2, 2, 161, 3, 2, 2, 2, 2, 163, 3, 2, 2, 2, 2, 165, 3, 2, 2, 2, 2, 167, 3, 2, 2, 2, 2, 169, 3, 2, 2, 2, 2, 171, 3, 2, 2, 2, 2, 173, 3, 2, 2, 2, 2, 175, 3, 2, 2, 2, 2, 177, 3, 2, 2, 2, 2, 179, 3, 2, 2, 2, 2, 181, 3, 2, 2, 2, 2, 183, 3, 2, 2, 2, 2, 185, 3, 2, 2, 2, 2, 187, 3, 2, 2, 2, 2, 189, 3, 2, 2, 2, 2, 191, 3, 2, 2, 2, 2, 193, 3, 2, 2, 2, 2, 195, 3, 2, 2, 2, 2, 197, 3, 2, 2, 2, 2, 199, 3, 2, 2, 2, 2, 201, 3, 2, 2, 2, 2, 203, 3, 2, 2, 2, 2, 205, 3, 2, 2, 2, 2, 207, 3, 2, 2, 2, 2, 215, 3, 2, 2, 2, 2, 217, 3, 2, 2, 2, 2, 219, 3, 2, 2, 2, 2, 221, 3, 2, 2, 2, 2, 223, 3, 2, 2, 2, 3, 241, 3, 2, 2, 2, 5, 243, 3, 2, 2, 2, 7, 245, 3, 2, 2, 2, 9, 247, 3, 2, 2, 2, 11, 249, 3, 2, 2, 2, 13, 251, 3, 2, 2, 2, 15, 253, 3, 2, 2, 2, 17, 255, 3, 2, 2, 2, 19, 257, 3, 2, 2, 2, 21, 259, 3, 2, 2, 2, 23, 261, 3, 2, 2, 2, 25, 263, 3, 2, 2, 2, 27, 265, 3, 2, 2, 2, 29, 267, 3, 2, 2, 2, 31, 269, 3, 2, 2, 2, 33, 271, 3, 2, 2, 2, 35, 273, 3, 2, 2, 2, 37, 275, 3, 2, 2, 2, 39, 277, 3, 2, 2, 2, 41, 279, 3, 2, 2, 2, 43, 281, 3, 2, 2, 2, 45, 283, 3, 2, 2, 2, 47, 285, 3, 2, 2, 2, 49, 287, 3, 2, 2, 2, 51, 289, 3, 2, 2, 2, 53, 291, 3, 2, 2, 2, 55, 293, 3, 2, 2, 2, 57, 296, 3, 2, 2, 2, 59, 300, 3, 2, 2, 2, 61, 320, 3, 2, 2, 2, 63, 339, 3, 2, 2, 2, 65, 341, 3, 2, 2, 2, 67, 344, 3, 2, 2, 2, 69, 353, 3, 2, 2, 2, 71, 363, 3, 2, 2, 2, 73, 368, 3, 2, 2, 2, 75, 377, 3, 2, 2, 2, 77, 382, 3, 2, 2, 2, 79, 386, 3, 2, 2, 2, 81, 390, 3, 2, 2, 2, 83, 393, 3, 2, 2, 2, 85, 399, 3, 2, 2, 2, 87, 402, 3, 2, 2, 2, 89, 407, 3, 2, 2, 2, 91, 414, 3, 2, 2, 2, 93, 421, 3, 2, 2, 2, 95, 426, 3, 2, 2, 2, 97, 431, 3, 2, 2, 2, 99, 437, 3, 2, 2, 2, 101, 442, 3, 2, 2, 2, 103, 448, 3, 2, 2, 2, 105, 455, 3, 2, 2, 2, 107, 460, 3, 2, 2, 2, 109, 464, 3, 2, 2, 2, 111, 468, 3, 2, 2, 2, 113, 472, 3, 2, 2, 2, 115, 475, 3, 2, 2, 2, 117, 481, 3, 2, 2, 2, 119, 484, 3, 2, 2, 2, 121, 492, 3, 2, 2, 2, 123, 499, 3, 2, 2, 2, 125, 506, 3, 2, 2, 2, 127, 512, 3, 2, 2, 2, 129, 519, 3, 2, 2, 2, 131, 526, 3, 2, 2, 2, 133, 532, 3, 2, 2, 2, 135, 538, 3, 2, 2, 2, 137, 543, 3, 2, 2, 2, 139, 547, 3, 2, 2, 2, 141, 549, 3, 2, 2, 2, 143, 552, 3, 2, 2, 2, 145, 556, 3, 2, 2, 2, 147, 559, 3, 2, 2, 2, 149, 561, 3, 2, 2, 2, 151, 564, 3, 2, 2, 2, 153, 566, 3, 2, 2, 2, 155, 569, 3, 2, 2, 2, 157, 574, 3, 2, 2, 2, 159, 576, 3, 2, 2, 2, 161, 578, 3, 2, 2, 2, 163, 580, 3, 2, 2, 2, 165, 582, 3, 2, 2, 2, 167, 584, 3, 2, 2, 2, 169, 586, 3, 2, 2, 2, 171, 588, 3, 2, 2, 2, 173, 591, 3, 2, 2, 2, 175, 594, 3, 2, 2, 2, 177, 597, 3, 2, 2, 2, 179, 599, 3, 2, 2, 2, 181, 601, 3, 2, 2, 2, 183, 604, 3, 2, 2, 2, 185, 606, 3, 2, 2, 2, 187, 608, 3, 2, 2, 2, 189, 610, 3, 2, 2, 2, 191, 612, 3, 2, 2, 2, 193, 614, 3, 2, 2, 2, 195, 616, 3, 2, 2, 2, 197, 618, 3, 2, 2, 2, 199, 620, 3, 2, 2, 2, 201, 622, 3, 2, 2, 2, 203, 624, 3, 2, 2, 2, 205, 662, 3, 2, 2, 2, 207, 664, 3, 2, 2, 2, 209, 667, 3, 2, 2, 2, 211, 669, 3, 2, 2, 2, 213, 671, 3, 2, 2, 2, 215, 686, 3, 2, 2, 2, 217, 702, 3, 2, 2, 2, 219, 722, 3, 2, 2, 2, 221, 726, 3, 2, 2, 2, 223, 735, 3, 2, 2, 2, 225, 749, 3, 2, 2, 2, 227, 752, 3, 2, 2, 2, 229, 757, 3, 2, 2, 2, 231, 761, 3, 2, 2, 2, 233, 764, 3, 2, 2, 2, 235, 769, 3, 2, 2, 2, 237, 771, 3, 2, 2, 2, 239, 773, 3, 2, 2, 2, 241, 242, 9, 2, 2, 2, 242, 4, 3, 2, 2, 2, 243, 244, 9, 3, 2, 2, 244, 6, 3, 2, 2, 2, 245, 246, 9, 4, 2, 2, 246, 8, 3, 2, 2, 2, 247, 248, 9, 5, 2, 2, 248, 10, 3, 2, 2, 2, 249, 250, 9, 6, 2, 2, 250, 12, 3, 2, 2, 2, 251, 252, 9, 7, 2, 2, 252, 14, 3, 2, 2, 2, 253, 254, 9, 8, 2, 2, 254, 16, 3, 2, 2, 2, 255, 256, 9, 9, 2, 2, 256, 18, 3, 2, 2, 2, 257, 258, 9, 10, 2, 2, 258, 20, 3, 2, 2, 2, 259, 260, 9, 11, 2, 2, 260, 22, 3, 2, 2, 2, 261, 262, 9, 12, 2, 2, 262, 24, 3, 2, 2, 2, 263, 264, 9, 13, 2, 2, 264, 26, 3, 2, 2, 2, 265, 266, 9, 14, 2, 2, 266, 28, 3, 2, 2, 2, 267, 268, 9, 15, 2, 2, 268, 30, 3, 2, 2, 2, 269, 270, 9, 16, 2, 2, 270, 32, 3, 2, 2, 2, 271, 272, 9, 17, 2, 2, 272, 34, 3, 2, 2, 2, 273, 274, 9, 18, 2, 2, 274, 36, 3, 2, 2, 2, 275, 276, 9, 19, 2, 2, 276, 38, 3, 2, 2, 2, 277, 278, 9, 20, 2, 2, 278, 40, 3, 2, 2, 2, 279, 280, 9, 21, 2, 2, 280, 42, 3, 2, 2, 2, 281, 282, 9, 22, 2, 2, 282, 44, 3, 2, 2, 2, 283, 284, 9, 23, 2, 2, 284, 46, 3, 2, 2, 2, 285, 286, 9, 24, 2, 2, 286, 48, 3, 2, 2, 2, 287, 288, 9, 25, 2, 2, 288, 50, 3, 2, 2, 2, 289, 290, 9, 26, 2, 2, 290, 52, 3, 2, 2, 2, 291, 292, 9, 27, 2, 2, 292, 54, 3, 2, 2, 2, 293, 294, 9, 28, 2, 2, 294, 56, 3, 2, 2, 2, 295, 297, 5, 55, 28, 2, 296, 295, 3, 2, 2, 2, 297, 298, 3, 2, 2, 2, 298, 296, 3, 2, 2, 2, 298, 299, 3, 2, 2, 2, 299, 58, 3, 2, 2, 2, 300, 301, 9, 29, 2, 2, 301, 60, 3, 2, 2, 2, 302, 303, 7, 50, 2, 2, 303, 304, 7, 122, 2, 2, 304, 306, 3, 2, 2, 2, 305, 307, 5, 59, 30, 2, 306, 305, 3, 2, 2, 2, 307, 308, 3, 2, 2, 2, 308, 306, 3, 2, 2, 2, 308, 309, 3, 2, 2, 2, 309, 321, 3, 2, 2, 2, 310, 311, 7, 122, 2, 2, 311, 312, 7, 41, 2, 2, 312, 314, 3, 2, 2, 2, 313, 315, 5, 59, 30, 2, 314, 313, 3, 2, 2, 2, 315, 316, 3, 2, 2, 2, 316, 314, 3, 2, 2, 2, 316, 317, 3, 2, 2, 2, 317, 318, 3, 2, 2, 2, 318, 319, 7, 41, 2, 2, 319, 321, 3, 2, 2, 2, 320, 302, 3, 2, 2, 2, 320, 310, 3, 2, 2, 2, 321, 62, 3, 2, 2, 2, 322, 323, 7, 50, 2, 2, 323, 324, 7, 100, 2, 2, 324, 326, 3, 2, 2, 2, 325, 327, 9, 30, 2, 2, 326, 325, 3, 2, 2, 2, 327, 328, 3, 2, 2, 2, 328, 326, 3, 2, 2, 2, 328, 329, 3, 2, 2, 2, 329, 340, 3, 2, 2, 2, 330, 331, 7, 100, 2, 2, 331, 332, 7, 41, 2, 2, 332, 334, 3, 2, 2, 2, 333, 335, 9, 30, 2, 2, 334, 333, 3, 2, 2, 2, 335, 336, 3, 2, 2, 2, 336, 334, 3, 2, 2, 2, 336, 337, 3, 2, 2, 2, 337, 338, 3, 2, 2, 2, 338, 340, 7, 41, 2, 2, 339, 322, 3, 2, 2, 2, 339, 330, 3, 2, 2, 2, 340, 64, 3, 2, 2, 2, 341, 342, 5, 57, 29, 2, 342, 66, 3, 2, 2, 2, 343, 345, 5, 57, 29, 2, 344, 343, 3, 2, 2, 2, 344, 345, 3, 2, 2, 2, 345, 346, 3, 2, 2, 2, 346, 347, 5, 185, 93, 2, 347, 348, 5, 57, 29, 2, 348, 68, 3, 2, 2, 2, 349, 351, 5, 57, 29, 2, 350, 349, 3, 2, 2, 2, 350, 351, 3, 2, 2, 2, 351, 352, 3, 2, 2, 2, 352, 354, 5, 185, 93, 2, 353, 350, 3, 2, 2, 2, 353, 354, 3, 2, 2, 2, 354, 355, 3, 2, 2, 2, 355, 356, 5, 57, 29, 2, 356, 359, 9, 6, 2, 2, 357, 360, 5, 159, 80, 2, 358, 360, 5, 157, 79, 2, 359, 357, 3, 2, 2, 2, 359, 358, 3, 2, 2, 2, 359, 360, 3, 2, 2, 2, 360, 361, 3, 2, 2, 2, 361, 362, 5, 57, 29, 2, 362, 70, 3, 2, 2, 2, 363, 364, 5, 39, 20, 2, 364, 365, 5, 17, 9, 2, 365, 366, 5, 31, 16, 2, 366, 367, 5, 47, 24, 2, 367, 72, 3, 2, 2, 2, 368, 369, 5, 11, 6, 2, 369, 370, 5, 49, 25, 2, 370, 371, 5, 11, 6, 2, 371, 372, 5, 7, 4, 2, 372, 373, 5, 13, 7, 2, 373, 374, 5, 19, 10, 2, 374, 375, 5, 25, 13, 2, 375, 376, 5, 11, 6, 2, 376, 74, 3, 2, 2, 2, 377, 378, 5, 35, 18, 2, 378, 379, 5, 43, 22, 2, 379, 380, 5, 19, 10, 2, 380, 381, 5, 41, 21, 2, 381, 76, 3, 2, 2, 2, 382, 383, 5, 3, 2, 2, 383, 384, 5, 29, 15, 2, 384, 385, 5, 9, 5, 2, 385, 78, 3, 2, 2, 2, 386, 387, 5, 3, 2, 2, 387, 388, 5, 39, 20, 2, 388, 389, 5, 7, 4, 2, 389, 80, 3, 2, 2, 2, 390, 391, 5, 3, 2, 2, 391, 392, 5, 39, 20, 2, 392, 82, 3, 2, 2, 2, 393, 394, 5, 5, 3, 2, 394, 395, 5, 11, 6, 2, 395, 396, 5, 15, 8, 2, 396, 397, 5, 19, 10, 2, 397, 398, 5, 29, 15, 2, 398, 84, 3, 2, 2, 2, 399, 400, 5, 5, 3, 2, 400, 401, 5, 51, 26, 2, 401, 86, 3, 2, 2, 2, 402, 403, 5, 7, 4, 2, 403, 404, 5, 17, 9, 2, 404, 405, 5, 3, 2, 2, 405, 406, 5, 37, 19, 2, 406, 88, 3, 2, 2, 2, 407, 408, 5, 7, 4, 2, 408, 409, 5, 37, 19, 2, 409, 410, 5, 11, 6, 2, 410, 411, 5, 3, 2, 2, 411, 412, 5, 41, 21, 2, 412, 413, 5, 11, 6, 2, 413, 90, 3, 2, 2, 2, 414, 415, 5, 9, 5, 2, 415, 416, 5, 11, 6, 2, 416, 417, 5, 25, 13, 2, 417, 418, 5, 11, 6, 2, 418, 419, 5, 41, 21, 2, 419, 420, 5, 11, 6, 2, 420, 92, 3, 2, 2, 2, 421, 422, 5, 9, 5, 2, 422, 423, 5, 11, 6, 2, 423, 424, 5, 39, 20, 2, 424, 425, 5, 7, 4, 2, 425, 94, 3, 2, 2, 2, 426, 427, 5, 9, 5, 2, 427, 428, 5, 37, 19, 2, 428, 429, 5, 31, 16, 2, 429, 430, 5, 33, 17, 2, 430, 96, 3, 2, 2, 2, 431, 432, 5, 13, 7, 2, 432, 433, 5, 25, 13, 2, 433, 434, 5, 31, 16, 2, 434, 435, 5, 3, 2, 2, 435, 436, 5, 41, 21, 2, 436, 98, 3, 2, 2, 2, 437, 438, 5, 13, 7, 2, 438, 439, 5, 37, 19, 2, 439, 440, 5, 31, 16, 2, 440, 441, 5, 27, 14, 2, 441, 100, 3, 2, 2, 2, 442, 443, 5, 19, 10, 2, 443, 444, 5, 29, 15, 2, 444, 445, 5, 9, 5, 2, 445, 446, 5, 11, 6, 2, 446, 447, 5, 49, 25, 2, 447, 102, 3, 2, 2, 2, 448, 449, 5, 19, 10, 2, 449, 450, 5, 29, 15, 2, 450, 451, 5, 39, 20, 2, 451, 452, 5, 11, 6, 2, 452, 453, 5, 37, 19, 2, 453, 454, 5, 41, 21, 2, 454, 104, 3, 2, 2, 2, 455, 456, 5, 19, 10, 2, 456, 457, 5, 29, 15, 2, 457, 458, 5, 41, 21, 2, 458, 459, 5, 31, 16, 2, 459, 106, 3, 2, 2, 2, 460, 461, 5, 19, 10, 2, 461, 462, 5, 29, 15, 2, 462, 463, 5, 41, 21, 2, 463, 108, 3, 2, 2, 2, 464, 465, 5, 23, 12, 2, 465, 466, 5, 11, 6, 2, 466, 467, 5, 51, 26, 2, 467, 110, 3, 2, 2, 2, 468, 469, 5, 29, 15, 2, 469, 470, 5, 31, 16, 2, 470, 471, 5, 41, 21, 2, 471, 112, 3, 2, 2, 2, 472, 473, 5, 31, 16, 2, 473, 474, 5, 29, 15, 2, 474, 114, 3, 2, 2, 2, 475, 476, 5, 31, 16, 2, 476, 477, 5, 37, 19, 2, 477, 478, 5, 9, 5, 2, 478, 479, 5, 11, 6, 2, 479, 480, 5, 37, 19, 2, 480, 116, 3, 2, 2, 2, 481, 482, 5, 31, 16, 2, 482, 483, 5, 37, 19, 2, 483, 118, 3, 2, 2, 2, 484, 485, 5, 33, 17, 2, 485, 486, 5, 37, 19, 2, 486, 487, 5, 19, 10, 2, 487, 488, 5, 27, 14, 2, 488, 489, 5, 3, 2, 2, 489, 490, 5, 37, 19, 2, 490, 491, 5, 51, 26, 2, 491, 120, 3, 2, 2, 2, 492, 493, 5, 39, 20, 2, 493, 494, 5, 11, 6, 2, 494, 495, 5, 25, 13, 2, 495, 496, 5, 11, 6, 2, 496, 497, 5, 7, 4, 2, 497, 498, 5, 41, 21, 2, 498, 122, 3, 2, 2, 2, 499, 500, 5, 41, 21, 2, 500, 501, 5, 3, 2, 2, 501, 502, 5, 5, 3, 2, 502, 503, 5, 25, 13, 2, 503, 504, 5, 11, 6, 2, 504, 505, 5, 39, 20, 2, 505, 124, 3, 2, 2, 2, 506, 507, 5, 41, 21, 2, 507, 508, 5, 3, 2, 2, 508, 509, 5, 5, 3, 2, 509, 510, 5, 25, 13, 2, 510, 511, 5, 11, 6, 2, 511, 126, 3, 2, 2, 2, 512, 513, 5, 43, 22, 2, 513, 514, 5, 29, 15, 2, 514, 515, 5, 19, 10, 2, 515, 516, 5, 35, 18, 2, 516, 517, 5, 43, 22, 2, 517, 518, 5, 11, 6, 2, 518, 128, 3, 2, 2, 2, 519, 520, 5, 45, 23, 2, 520, 521, 5, 3, 2, 2, 521, 522, 5, 25, 13, 2, 522, 523, 5, 43, 22, 2, 523, 524, 5, 11, 6, 2, 524, 525, 5, 39, 20, 2, 525, 130, 3, 2, 2, 2, 526, 527, 5, 45, 23, 2, 527, 528, 5, 3, 2, 2, 528, 529, 5, 25, 13, 2, 529, 530, 5, 43, 22, 2, 530, 531, 5, 11, 6, 2, 531, 132, 3, 2, 2, 2, 532, 533, 5, 47, 24, 2, 533, 534, 5, 17, 9, 2, 534, 535, 5, 11, 6, 2, 535, 536, 5, 37, 19, 2, 536, 537, 5, 11, 6, 2, 537, 134, 3, 2, 2, 2, 538, 539, 5, 47, 24, 2, 539, 540, 5, 31, 16, 2, 540, 541, 5, 37, 19, 2, 541, 542, 5, 23, 12, 2, 542, 136, 3, 2, 2, 2, 543, 544, 5, 49, 25, 2, 544, 545, 5, 31, 16, 2, 545, 546, 5, 37, 19, 2, 546, 138, 3, 2, 2, 2, 547, 548, 7, 63, 2, 2, 548, 140, 3, 2, 2, 2, 549, 550, 7, 60, 2, 2, 550, 551, 7, 63, 2, 2, 551, 142, 3, 2, 2, 2, 552, 553, 7, 62, 2, 2, 553, 554, 7, 63, 2, 2, 554, 555, 7, 64, 2, 2, 555, 144, 3, 2, 2, 2, 556, 557, 7, 64, 2, 2, 557, 558, 7, 63, 2, 2, 558, 146, 3, 2, 2, 2, 559, 560, 7, 64, 2, 2, 560, 148, 3, 2, 2, 2, 561, 562, 7, 62, 2, 2, 562, 563, 7, 63, 2, 2, 563, 150, 3, 2, 2, 2, 564, 565, 7, 62, 2, 2, 565, 152, 3, 2, 2, 2, 566, 567, 7, 35, 2, 2, 567, 568, 7, 63, 2, 2, 568, 154, 3, 2, 2, 2, 569, 570, 7, 62, 2, 2, 570, 571, 7, 64, 2, 2, 571, 572, 3, 2, 2, 2, 572, 573, 8, 78, 2, 2, 573, 156, 3, 2, 2, 2, 574, 575, 7, 45, 2, 2, 575, 158, 3, 2, 2, 2, 576, 577, 7, 47, 2, 2, 577, 160, 3, 2, 2, 2, 578, 579, 7, 44, 2, 2, 579, 162, 3, 2, 2, 2, 580, 581, 7, 49, 2, 2, 581, 164, 3, 2, 2, 2, 582, 583, 7, 39, 2, 2, 583, 166, 3, 2, 2, 2, 584, 585, 7, 35, 2, 2, 585, 168, 3, 2, 2, 2, 586, 587, 7, 128, 2, 2, 587, 170, 3, 2, 2, 2, 588, 589, 7, 62, 2, 2, 589, 590, 7, 62, 2, 2, 590, 172, 3, 2, 2, 2, 591, 592, 7, 64, 2, 2, 592, 593, 7, 64, 2, 2, 593, 174, 3, 2, 2, 2, 594, 595, 7, 40, 2, 2, 595, 596, 7, 40, 2, 2, 596, 176, 3, 2, 2, 2, 597, 598, 7, 40, 2, 2, 598, 178, 3, 2, 2, 2, 599, 600, 7, 96, 2, 2, 600, 180, 3, 2, 2, 2, 601, 602, 7, 126, 2, 2, 602, 603, 7, 126, 2, 2, 603, 182, 3, 2, 2, 2, 604, 605, 7, 126, 2, 2, 605, 184, 3, 2, 2, 2, 606, 607, 7, 48, 2, 2, 607, 186, 3, 2, 2, 2, 608, 609, 7, 46, 2, 2, 609, 188, 3, 2, 2, 2, 610, 611, 7, 61, 2, 2, 611, 190, 3, 2, 2, 2, 612, 613, 7, 60, 2, 2, 613, 192, 3, 2, 2, 2, 614, 615, 7, 42, 2, 2, 615, 194, 3, 2, 2, 2, 616, 617, 7, 43, 2, 2, 617, 196, 3, 2, 2, 2, 618, 619, 7, 125, 2, 2, 619, 198, 3, 2, 2, 2, 620, 621, 7, 127, 2, 2, 621, 200, 3, 2, 2, 2, 622, 623, 7, 97, 2, 2, 623, 202, 3, 2, 2, 2, 624, 625, 9, 31, 2, 2, 625, 626, 3, 2, 2, 2, 626, 627, 8, 102, 3, 2, 627, 204, 3, 2, 2, 2, 628, 630, 5, 57, 29, 2, 629, 628, 3, 2, 2, 2, 630, 631, 3, 2, 2, 2, 631, 629, 3, 2, 2, 2, 631, 632, 3, 2, 2, 2, 632, 633, 3, 2, 2, 2, 633, 641, 9, 6, 2, 2, 634, 638, 5, 237, 119, 2, 635, 637, 5, 235, 118, 2, 636, 635, 3, 2, 2, 2, 637, 640, 3, 2, 2, 2, 638, 636, 3, 2, 2, 2, 638, 639, 3, 2, 2, 2, 639, 642, 3, 2, 2, 2, 640, 638, 3, 2, 2, 2, 641, 634, 3, 2, 2, 2, 641, 642, 3, 2, 2, 2, 642, 663, 3, 2, 2, 2, 643, 645, 5, 57, 29, 2, 644, 643, 3, 2, 2, 2, 645, 646, 3, 2, 2, 2, 646, 644, 3, 2, 2, 2, 646, 647, 3, 2, 2, 2, 647, 648, 3, 2, 2, 2, 648, 652, 5, 239, 120, 2, 649, 651, 5, 235, 118, 2, 650, 649, 3, 2, 2, 2, 651, 654, 3, 2, 2, 2, 652, 650, 3, 2, 2, 2, 652, 653, 3, 2, 2, 2, 653, 663, 3, 2, 2, 2, 654, 652, 3, 2, 2, 2, 655, 659, 5, 237, 119, 2, 656, 658, 5, 235, 118, 2, 657, 656, 3, 2, 2, 2, 658, 661, 3, 2, 2, 2, 659, 657, 3, 2, 2, 2, 659, 660, 3, 2, 2, 2, 660, 663, 3, 2, 2, 2, 661, 659, 3, 2, 2, 2, 662, 629, 3, 2, 2, 2, 662, 644, 3, 2, 2, 2, 662, 655, 3, 2, 2, 2, 663, 206, 3, 2, 2, 2, 664, 665, 9, 15, 2, 2, 665, 666, 5, 217, 109, 2, 666, 208, 3, 2, 2, 2, 667, 668, 7, 98, 2, 2, 668, 210, 3, 2, 2, 2, 669, 670, 7, 41, 2, 2, 670, 212, 3, 2, 2, 2, 671, 672, 7, 36, 2, 2, 672, 214, 3, 2, 2, 2, 673, 681, 5, 213, 107, 2, 674, 675, 7, 94, 2, 2, 675, 677, 11, 2, 2, 2, 676, 674, 3, 2, 2, 2, 676, 677, 3, 2, 2, 2, 677, 678, 3, 2, 2, 2, 678, 680, 11, 2, 2, 2, 679, 676, 3, 2, 2, 2, 680, 683, 3, 2, 2, 2, 681, 682, 3, 2, 2, 2, 681, 679, 3, 2, 2, 2, 682, 684, 3, 2, 2, 2, 683, 681, 3, 2, 2, 2, 684, 685, 5, 213, 107, 2, 685, 687, 3, 2, 2, 2, 686, 673, 3, 2, 2, 2, 687, 688, 3, 2, 2, 2, 688, 686, 3, 2, 2, 2, 688, 689, 3, 2, 2, 2, 689, 216, 3, 2, 2, 2, 690, 697, 5, 211, 106, 2, 691, 693, 7, 94, 2, 2, 692, 691, 3, 2, 2, 2, 692, 693, 3, 2, 2, 2, 693, 694, 3, 2, 2, 2, 694, 696, 11, 2, 2, 2, 695, 692, 3, 2, 2, 2, 696, 699, 3, 2, 2, 2, 697, 698, 3, 2, 2, 2, 697, 695, 3, 2, 2, 2, 698, 700, 3, 2, 2, 2, 699, 697, 3, 2, 2, 2, 700, 701, 5, 211, 106, 2, 701, 703, 3, 2, 2, 2, 702, 690, 3, 2, 2, 2, 703, 704, 3, 2, 2, 2, 704, 702, 3, 2, 2, 2, 704, 705, 3, 2, 2, 2, 705, 218, 3, 2, 2, 2, 706, 707, 7, 49, 2, 2, 707, 708, 7, 44, 2, 2, 708, 709, 7, 44, 2, 2, 709, 723, 7, 49, 2, 2, 710, 711, 7, 49, 2, 2, 711, 712, 7, 44, 2, 2, 712, 713, 3, 2, 2, 2, 713, 717, 10, 32, 2, 2, 714, 716, 11, 2, 2, 2, 715, 714, 3, 2, 2, 2, 716, 719, 3, 2, 2, 2, 717, 718, 3, 2, 2, 2, 717, 715, 3, 2, 2, 2, 718, 720, 3, 2, 2, 2, 719, 717, 3, 2, 2, 2, 720, 721, 7, 44, 2, 2, 721, 723, 7, 49, 2, 2, 722, 706, 3, 2, 2, 2, 722, 710, 3, 2, 2, 2, 723, 724, 3, 2, 2, 2, 724, 725, 8, 110, 3, 2, 725, 220, 3, 2, 2, 2, 726, 730, 7, 37, 2, 2, 727, 729, 10, 33, 2, 2, 728, 727, 3, 2, 2, 2, 729, 732, 3, 2, 2, 2, 730, 728, 3, 2, 2, 2, 730, 731, 3, 2, 2, 2, 731, 733, 3, 2, 2, 2, 732, 730, 3, 2, 2, 2, 733, 734, 8, 111, 3, 2, 734, 222, 3, 2, 2, 2, 735, 745, 5, 225, 113, 2, 736, 740, 9, 34, 2, 2, 737, 739, 10, 33, 2, 2, 738, 737, 3, 2, 2, 2, 739, 742, 3, 2, 2, 2, 740, 738, 3, 2, 2, 2, 740, 741, 3, 2, 2, 2, 741, 746, 3, 2, 2, 2, 742, 740, 3, 2, 2, 2, 743, 746, 5, 227, 114, 2, 744, 746, 7, 2, 2, 3, 745, 736, 3, 2, 2, 2, 745, 743, 3, 2, 2, 2, 745, 744, 3, 2, 2, 2, 746, 747, 3, 2, 2, 2, 747, 748, 8, 112, 3, 2, 748, 224, 3, 2, 2, 2, 749, 750, 7, 47, 2, 2, 750, 751, 7, 47, 2, 2, 751, 226, 3, 2, 2, 2, 752, 753, 9, 33, 2, 2, 753, 228, 3, 2, 2, 2, 754, 758, 5, 55, 28, 2, 755, 758, 9, 35, 2, 2, 756, 758, 5, 185, 93, 2, 757, 754, 3, 2, 2, 2, 757, 755, 3, 2, 2, 2, 757, 756, 3, 2, 2, 2, 758, 759, 3, 2, 2, 2, 759, 757, 3, 2, 2, 2, 759, 760, 3, 2, 2, 2, 760, 230, 3, 2, 2, 2, 761, 762, 7, 49, 2, 2, 762, 763, 7, 44, 2, 2, 763, 232, 3, 2, 2, 2, 764, 765, 7, 44, 2, 2, 765, 766, 7, 49, 2, 2, 766, 234, 3, 2, 2, 2, 767, 770, 5, 55, 28, 2, 768, 770, 5, 237, 119, 2, 769, 767, 3, 2, 2, 2, 769, 768, 3, 2, 2, 2, 770, 236, 3, 2, 2, 2, 771, 772, 9, 36, 2, 2, 772, 238, 3, 2, 2, 2, 773, 774, 9, 37, 2, 2, 774, 240, 3, 2, 2, 2, 35, 2, 298, 308, 316, 320, 328, 336, 339, 344, 350, 353, 359, 631, 638, 641, 646, 652, 659, 662, 676, 681, 688, 692, 697, 704, 717, 722, 730, 740, 745, 757, 759, 769, 4, 9, 49, 2, 2, 3, 2] \ No newline at end of file diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.tokens b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.tokens index 812dcb3..4df5972 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.tokens +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLLexer.tokens @@ -3,108 +3,109 @@ BIN_NUMBER=2 INT_NUMBER=3 DECIMAL_NUMBER=4 FLOAT_NUMBER=5 -EXECFILE_SYMBOL=6 -QUIT_SYMBOL=7 -AND_SYMBOL=8 -ASC_SYMBOL=9 -AS_SYMBOL=10 -BEGIN_SYMBOL=11 -BY_SYMBOL=12 -CHAR_SYMBOL=13 -CREATE_SYMBOL=14 -DELETE_SYMBOL=15 -DESC_SYMBOL=16 -DROP_SYMBOL=17 -FLOAT_SYMBOL=18 -FROM_SYMBOL=19 -INDEX_SYMBOL=20 -INSERT_SYMBOL=21 -INTO_SYMBOL=22 -INT_SYMBOL=23 -KEY_SYMBOL=24 -NOT_SYMBOL=25 -ON_SYMBOL=26 -ORDER_SYMBOL=27 -OR_SYMBOL=28 -PRIMARY_SYMBOL=29 -SELECT_SYMBOL=30 -TABLES_SYMBOL=31 -TABLE_SYMBOL=32 -UNIQUE_SYMBOL=33 -VALUES_SYMBOL=34 -VALUE_SYMBOL=35 -WHERE_SYMBOL=36 -WORK_SYMBOL=37 -XOR_SYMBOL=38 -EQUAL_OPERATOR=39 -ASSIGN_OPERATOR=40 -NULL_SAFE_EQUAL_OPERATOR=41 -GREATER_OR_EQUAL_OPERATOR=42 -GREATER_THAN_OPERATOR=43 -LESS_OR_EQUAL_OPERATOR=44 -LESS_THAN_OPERATOR=45 -NOT_EQUAL_OPERATOR=46 -PLUS_OPERATOR=47 -MINUS_OPERATOR=48 -MULT_OPERATOR=49 -DIV_OPERATOR=50 -MOD_OPERATOR=51 -LOGICAL_NOT_OPERATOR=52 -BITWISE_NOT_OPERATOR=53 -SHIFT_LEFT_OPERATOR=54 -SHIFT_RIGHT_OPERATOR=55 -LOGICAL_AND_OPERATOR=56 -BITWISE_AND_OPERATOR=57 -BITWISE_XOR_OPERATOR=58 -LOGICAL_OR_OPERATOR=59 -BITWISE_OR_OPERATOR=60 -DOT_SYMBOL=61 -COMMA_SYMBOL=62 -SEMICOLON_SYMBOL=63 -COLON_SYMBOL=64 -OPEN_PAR_SYMBOL=65 -CLOSE_PAR_SYMBOL=66 -OPEN_CURLY_SYMBOL=67 -CLOSE_CURLY_SYMBOL=68 -UNDERLINE_SYMBOL=69 -WHITESPACE=70 -IDENTIFIER=71 -NCHAR_TEXT=72 -DOUBLE_QUOTED_TEXT=73 -SINGLE_QUOTED_TEXT=74 -BLOCK_COMMENT=75 -POUND_COMMENT=76 -DASHDASH_COMMENT=77 -NOT_EQUAL2_OPERATOR=78 -'='=39 -':='=40 -'<=>'=41 -'>='=42 -'>'=43 -'<='=44 -'<'=45 -'!='=46 -''=78 -'+'=47 -'-'=48 -'*'=49 -'/'=50 -'%'=51 -'!'=52 -'~'=53 -'<<'=54 -'>>'=55 -'&&'=56 -'&'=57 -'^'=58 -'||'=59 -'|'=60 -'.'=61 -','=62 -';'=63 -':'=64 -'('=65 -')'=66 -'{'=67 -'}'=68 -'_'=69 +SHOW_SYMBOL=6 +EXECFILE_SYMBOL=7 +QUIT_SYMBOL=8 +AND_SYMBOL=9 +ASC_SYMBOL=10 +AS_SYMBOL=11 +BEGIN_SYMBOL=12 +BY_SYMBOL=13 +CHAR_SYMBOL=14 +CREATE_SYMBOL=15 +DELETE_SYMBOL=16 +DESC_SYMBOL=17 +DROP_SYMBOL=18 +FLOAT_SYMBOL=19 +FROM_SYMBOL=20 +INDEX_SYMBOL=21 +INSERT_SYMBOL=22 +INTO_SYMBOL=23 +INT_SYMBOL=24 +KEY_SYMBOL=25 +NOT_SYMBOL=26 +ON_SYMBOL=27 +ORDER_SYMBOL=28 +OR_SYMBOL=29 +PRIMARY_SYMBOL=30 +SELECT_SYMBOL=31 +TABLES_SYMBOL=32 +TABLE_SYMBOL=33 +UNIQUE_SYMBOL=34 +VALUES_SYMBOL=35 +VALUE_SYMBOL=36 +WHERE_SYMBOL=37 +WORK_SYMBOL=38 +XOR_SYMBOL=39 +EQUAL_OPERATOR=40 +ASSIGN_OPERATOR=41 +NULL_SAFE_EQUAL_OPERATOR=42 +GREATER_OR_EQUAL_OPERATOR=43 +GREATER_THAN_OPERATOR=44 +LESS_OR_EQUAL_OPERATOR=45 +LESS_THAN_OPERATOR=46 +NOT_EQUAL_OPERATOR=47 +PLUS_OPERATOR=48 +MINUS_OPERATOR=49 +MULT_OPERATOR=50 +DIV_OPERATOR=51 +MOD_OPERATOR=52 +LOGICAL_NOT_OPERATOR=53 +BITWISE_NOT_OPERATOR=54 +SHIFT_LEFT_OPERATOR=55 +SHIFT_RIGHT_OPERATOR=56 +LOGICAL_AND_OPERATOR=57 +BITWISE_AND_OPERATOR=58 +BITWISE_XOR_OPERATOR=59 +LOGICAL_OR_OPERATOR=60 +BITWISE_OR_OPERATOR=61 +DOT_SYMBOL=62 +COMMA_SYMBOL=63 +SEMICOLON_SYMBOL=64 +COLON_SYMBOL=65 +OPEN_PAR_SYMBOL=66 +CLOSE_PAR_SYMBOL=67 +OPEN_CURLY_SYMBOL=68 +CLOSE_CURLY_SYMBOL=69 +UNDERLINE_SYMBOL=70 +WHITESPACE=71 +IDENTIFIER=72 +NCHAR_TEXT=73 +DOUBLE_QUOTED_TEXT=74 +SINGLE_QUOTED_TEXT=75 +BLOCK_COMMENT=76 +POUND_COMMENT=77 +DASHDASH_COMMENT=78 +NOT_EQUAL2_OPERATOR=79 +'='=40 +':='=41 +'<=>'=42 +'>='=43 +'>'=44 +'<='=45 +'<'=46 +'!='=47 +''=79 +'+'=48 +'-'=49 +'*'=50 +'/'=51 +'%'=52 +'!'=53 +'~'=54 +'<<'=55 +'>>'=56 +'&&'=57 +'&'=58 +'^'=59 +'||'=60 +'|'=61 +'.'=62 +','=63 +';'=64 +':'=65 +'('=66 +')'=67 +'{'=68 +'}'=69 +'_'=70 diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLListener.cs b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLListener.cs index 8768722..2956755 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLListener.cs +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLListener.cs @@ -71,6 +71,16 @@ public interface IMiniSQLListener : IParseTreeListener { /// The parse tree. void ExitExecFileStatement([NotNull] MiniSQLParser.ExecFileStatementContext context); /// + /// Enter a parse tree produced by . + /// + /// The parse tree. + void EnterShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context); + /// + /// Exit a parse tree produced by . + /// + /// The parse tree. + void ExitShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context); + /// /// Enter a parse tree produced by . /// /// The parse tree. diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLParser.cs b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLParser.cs index 8b994f0..c2a8668 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLParser.cs +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLParser.cs @@ -37,80 +37,82 @@ public partial class MiniSQLParser : Parser { protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); public const int HEX_NUMBER=1, BIN_NUMBER=2, INT_NUMBER=3, DECIMAL_NUMBER=4, FLOAT_NUMBER=5, - EXECFILE_SYMBOL=6, QUIT_SYMBOL=7, AND_SYMBOL=8, ASC_SYMBOL=9, AS_SYMBOL=10, - BEGIN_SYMBOL=11, BY_SYMBOL=12, CHAR_SYMBOL=13, CREATE_SYMBOL=14, DELETE_SYMBOL=15, - DESC_SYMBOL=16, DROP_SYMBOL=17, FLOAT_SYMBOL=18, FROM_SYMBOL=19, INDEX_SYMBOL=20, - INSERT_SYMBOL=21, INTO_SYMBOL=22, INT_SYMBOL=23, KEY_SYMBOL=24, NOT_SYMBOL=25, - ON_SYMBOL=26, ORDER_SYMBOL=27, OR_SYMBOL=28, PRIMARY_SYMBOL=29, SELECT_SYMBOL=30, - TABLES_SYMBOL=31, TABLE_SYMBOL=32, UNIQUE_SYMBOL=33, VALUES_SYMBOL=34, - VALUE_SYMBOL=35, WHERE_SYMBOL=36, WORK_SYMBOL=37, XOR_SYMBOL=38, EQUAL_OPERATOR=39, - ASSIGN_OPERATOR=40, NULL_SAFE_EQUAL_OPERATOR=41, GREATER_OR_EQUAL_OPERATOR=42, - GREATER_THAN_OPERATOR=43, LESS_OR_EQUAL_OPERATOR=44, LESS_THAN_OPERATOR=45, - NOT_EQUAL_OPERATOR=46, PLUS_OPERATOR=47, MINUS_OPERATOR=48, MULT_OPERATOR=49, - DIV_OPERATOR=50, MOD_OPERATOR=51, LOGICAL_NOT_OPERATOR=52, BITWISE_NOT_OPERATOR=53, - SHIFT_LEFT_OPERATOR=54, SHIFT_RIGHT_OPERATOR=55, LOGICAL_AND_OPERATOR=56, - BITWISE_AND_OPERATOR=57, BITWISE_XOR_OPERATOR=58, LOGICAL_OR_OPERATOR=59, - BITWISE_OR_OPERATOR=60, DOT_SYMBOL=61, COMMA_SYMBOL=62, SEMICOLON_SYMBOL=63, - COLON_SYMBOL=64, OPEN_PAR_SYMBOL=65, CLOSE_PAR_SYMBOL=66, OPEN_CURLY_SYMBOL=67, - CLOSE_CURLY_SYMBOL=68, UNDERLINE_SYMBOL=69, WHITESPACE=70, IDENTIFIER=71, - NCHAR_TEXT=72, DOUBLE_QUOTED_TEXT=73, SINGLE_QUOTED_TEXT=74, BLOCK_COMMENT=75, - POUND_COMMENT=76, DASHDASH_COMMENT=77, NOT_EQUAL2_OPERATOR=78; + SHOW_SYMBOL=6, EXECFILE_SYMBOL=7, QUIT_SYMBOL=8, AND_SYMBOL=9, ASC_SYMBOL=10, + AS_SYMBOL=11, BEGIN_SYMBOL=12, BY_SYMBOL=13, CHAR_SYMBOL=14, CREATE_SYMBOL=15, + DELETE_SYMBOL=16, DESC_SYMBOL=17, DROP_SYMBOL=18, FLOAT_SYMBOL=19, FROM_SYMBOL=20, + INDEX_SYMBOL=21, INSERT_SYMBOL=22, INTO_SYMBOL=23, INT_SYMBOL=24, KEY_SYMBOL=25, + NOT_SYMBOL=26, ON_SYMBOL=27, ORDER_SYMBOL=28, OR_SYMBOL=29, PRIMARY_SYMBOL=30, + SELECT_SYMBOL=31, TABLES_SYMBOL=32, TABLE_SYMBOL=33, UNIQUE_SYMBOL=34, + VALUES_SYMBOL=35, VALUE_SYMBOL=36, WHERE_SYMBOL=37, WORK_SYMBOL=38, XOR_SYMBOL=39, + EQUAL_OPERATOR=40, ASSIGN_OPERATOR=41, NULL_SAFE_EQUAL_OPERATOR=42, GREATER_OR_EQUAL_OPERATOR=43, + GREATER_THAN_OPERATOR=44, LESS_OR_EQUAL_OPERATOR=45, LESS_THAN_OPERATOR=46, + NOT_EQUAL_OPERATOR=47, PLUS_OPERATOR=48, MINUS_OPERATOR=49, MULT_OPERATOR=50, + DIV_OPERATOR=51, MOD_OPERATOR=52, LOGICAL_NOT_OPERATOR=53, BITWISE_NOT_OPERATOR=54, + SHIFT_LEFT_OPERATOR=55, SHIFT_RIGHT_OPERATOR=56, LOGICAL_AND_OPERATOR=57, + BITWISE_AND_OPERATOR=58, BITWISE_XOR_OPERATOR=59, LOGICAL_OR_OPERATOR=60, + BITWISE_OR_OPERATOR=61, DOT_SYMBOL=62, COMMA_SYMBOL=63, SEMICOLON_SYMBOL=64, + COLON_SYMBOL=65, OPEN_PAR_SYMBOL=66, CLOSE_PAR_SYMBOL=67, OPEN_CURLY_SYMBOL=68, + CLOSE_CURLY_SYMBOL=69, UNDERLINE_SYMBOL=70, WHITESPACE=71, IDENTIFIER=72, + NCHAR_TEXT=73, DOUBLE_QUOTED_TEXT=74, SINGLE_QUOTED_TEXT=75, BLOCK_COMMENT=76, + POUND_COMMENT=77, DASHDASH_COMMENT=78, NOT_EQUAL2_OPERATOR=79; public const int RULE_prog = 0, RULE_simpleStatement = 1, RULE_quitStatement = 2, RULE_execFileStatement = 3, - RULE_createStatement = 4, RULE_createTable = 5, RULE_createIndex = 6, - RULE_dropStatement = 7, RULE_deleteStatement = 8, RULE_insertStatement = 9, - RULE_selectStatement = 10, RULE_queryExpression = 11, RULE_fromClause = 12, - RULE_queryExpressionParens = 13, RULE_dropIndex = 14, RULE_dropTable = 15, - RULE_insertValues = 16, RULE_valueList = 17, RULE_values = 18, RULE_whereClause = 19, - RULE_tableElementList = 20, RULE_tableElement = 21, RULE_tableConstraintDef = 22, - RULE_columnDefinition = 23, RULE_fieldDefinition = 24, RULE_dataType = 25, - RULE_fieldLength = 26, RULE_columnAttribute = 27, RULE_createIndexTarget = 28, - RULE_keyListVariants = 29, RULE_tableName = 30, RULE_columnName = 31, - RULE_keyPart = 32, RULE_indexRef = 33, RULE_tableRef = 34, RULE_fieldIdentifier = 35, - RULE_indexName = 36, RULE_pureIdentifier = 37, RULE_identifier = 38, RULE_qualifiedIdentifier = 39, - RULE_expr = 40, RULE_compOp = 41, RULE_atom = 42, RULE_scientific = 43, - RULE_variable = 44; + RULE_showTablesStatement = 4, RULE_createStatement = 5, RULE_createTable = 6, + RULE_createIndex = 7, RULE_dropStatement = 8, RULE_deleteStatement = 9, + RULE_insertStatement = 10, RULE_selectStatement = 11, RULE_queryExpression = 12, + RULE_fromClause = 13, RULE_queryExpressionParens = 14, RULE_dropIndex = 15, + RULE_dropTable = 16, RULE_insertValues = 17, RULE_valueList = 18, RULE_values = 19, + RULE_whereClause = 20, RULE_tableElementList = 21, RULE_tableElement = 22, + RULE_tableConstraintDef = 23, RULE_columnDefinition = 24, RULE_fieldDefinition = 25, + RULE_dataType = 26, RULE_fieldLength = 27, RULE_columnAttribute = 28, + RULE_createIndexTarget = 29, RULE_keyListVariants = 30, RULE_tableName = 31, + RULE_columnName = 32, RULE_keyPart = 33, RULE_indexRef = 34, RULE_tableRef = 35, + RULE_fieldIdentifier = 36, RULE_indexName = 37, RULE_pureIdentifier = 38, + RULE_identifier = 39, RULE_qualifiedIdentifier = 40, RULE_expr = 41, RULE_compOp = 42, + RULE_atom = 43, RULE_scientific = 44, RULE_variable = 45; public static readonly string[] ruleNames = { - "prog", "simpleStatement", "quitStatement", "execFileStatement", "createStatement", - "createTable", "createIndex", "dropStatement", "deleteStatement", "insertStatement", - "selectStatement", "queryExpression", "fromClause", "queryExpressionParens", - "dropIndex", "dropTable", "insertValues", "valueList", "values", "whereClause", - "tableElementList", "tableElement", "tableConstraintDef", "columnDefinition", - "fieldDefinition", "dataType", "fieldLength", "columnAttribute", "createIndexTarget", - "keyListVariants", "tableName", "columnName", "keyPart", "indexRef", "tableRef", - "fieldIdentifier", "indexName", "pureIdentifier", "identifier", "qualifiedIdentifier", - "expr", "compOp", "atom", "scientific", "variable" + "prog", "simpleStatement", "quitStatement", "execFileStatement", "showTablesStatement", + "createStatement", "createTable", "createIndex", "dropStatement", "deleteStatement", + "insertStatement", "selectStatement", "queryExpression", "fromClause", + "queryExpressionParens", "dropIndex", "dropTable", "insertValues", "valueList", + "values", "whereClause", "tableElementList", "tableElement", "tableConstraintDef", + "columnDefinition", "fieldDefinition", "dataType", "fieldLength", "columnAttribute", + "createIndexTarget", "keyListVariants", "tableName", "columnName", "keyPart", + "indexRef", "tableRef", "fieldIdentifier", "indexName", "pureIdentifier", + "identifier", "qualifiedIdentifier", "expr", "compOp", "atom", "scientific", + "variable" }; private static readonly string[] _LiteralNames = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, "'='", "':='", "'<=>'", "'>='", "'>'", "'<='", "'<'", - "'!='", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "'~'", "'<<'", "'>>'", - "'&&'", "'&'", "'^'", "'||'", "'|'", "'.'", "','", "';'", "':'", "'('", - "')'", "'{'", "'}'", "'_'", null, null, null, null, null, null, null, - null, "''" + null, null, null, null, "'='", "':='", "'<=>'", "'>='", "'>'", "'<='", + "'<'", "'!='", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "'~'", "'<<'", + "'>>'", "'&&'", "'&'", "'^'", "'||'", "'|'", "'.'", "','", "';'", "':'", + "'('", "')'", "'{'", "'}'", "'_'", null, null, null, null, null, null, + null, null, "''" }; private static readonly string[] _SymbolicNames = { null, "HEX_NUMBER", "BIN_NUMBER", "INT_NUMBER", "DECIMAL_NUMBER", "FLOAT_NUMBER", - "EXECFILE_SYMBOL", "QUIT_SYMBOL", "AND_SYMBOL", "ASC_SYMBOL", "AS_SYMBOL", - "BEGIN_SYMBOL", "BY_SYMBOL", "CHAR_SYMBOL", "CREATE_SYMBOL", "DELETE_SYMBOL", - "DESC_SYMBOL", "DROP_SYMBOL", "FLOAT_SYMBOL", "FROM_SYMBOL", "INDEX_SYMBOL", - "INSERT_SYMBOL", "INTO_SYMBOL", "INT_SYMBOL", "KEY_SYMBOL", "NOT_SYMBOL", - "ON_SYMBOL", "ORDER_SYMBOL", "OR_SYMBOL", "PRIMARY_SYMBOL", "SELECT_SYMBOL", - "TABLES_SYMBOL", "TABLE_SYMBOL", "UNIQUE_SYMBOL", "VALUES_SYMBOL", "VALUE_SYMBOL", - "WHERE_SYMBOL", "WORK_SYMBOL", "XOR_SYMBOL", "EQUAL_OPERATOR", "ASSIGN_OPERATOR", - "NULL_SAFE_EQUAL_OPERATOR", "GREATER_OR_EQUAL_OPERATOR", "GREATER_THAN_OPERATOR", - "LESS_OR_EQUAL_OPERATOR", "LESS_THAN_OPERATOR", "NOT_EQUAL_OPERATOR", - "PLUS_OPERATOR", "MINUS_OPERATOR", "MULT_OPERATOR", "DIV_OPERATOR", "MOD_OPERATOR", - "LOGICAL_NOT_OPERATOR", "BITWISE_NOT_OPERATOR", "SHIFT_LEFT_OPERATOR", - "SHIFT_RIGHT_OPERATOR", "LOGICAL_AND_OPERATOR", "BITWISE_AND_OPERATOR", - "BITWISE_XOR_OPERATOR", "LOGICAL_OR_OPERATOR", "BITWISE_OR_OPERATOR", - "DOT_SYMBOL", "COMMA_SYMBOL", "SEMICOLON_SYMBOL", "COLON_SYMBOL", "OPEN_PAR_SYMBOL", - "CLOSE_PAR_SYMBOL", "OPEN_CURLY_SYMBOL", "CLOSE_CURLY_SYMBOL", "UNDERLINE_SYMBOL", - "WHITESPACE", "IDENTIFIER", "NCHAR_TEXT", "DOUBLE_QUOTED_TEXT", "SINGLE_QUOTED_TEXT", - "BLOCK_COMMENT", "POUND_COMMENT", "DASHDASH_COMMENT", "NOT_EQUAL2_OPERATOR" + "SHOW_SYMBOL", "EXECFILE_SYMBOL", "QUIT_SYMBOL", "AND_SYMBOL", "ASC_SYMBOL", + "AS_SYMBOL", "BEGIN_SYMBOL", "BY_SYMBOL", "CHAR_SYMBOL", "CREATE_SYMBOL", + "DELETE_SYMBOL", "DESC_SYMBOL", "DROP_SYMBOL", "FLOAT_SYMBOL", "FROM_SYMBOL", + "INDEX_SYMBOL", "INSERT_SYMBOL", "INTO_SYMBOL", "INT_SYMBOL", "KEY_SYMBOL", + "NOT_SYMBOL", "ON_SYMBOL", "ORDER_SYMBOL", "OR_SYMBOL", "PRIMARY_SYMBOL", + "SELECT_SYMBOL", "TABLES_SYMBOL", "TABLE_SYMBOL", "UNIQUE_SYMBOL", "VALUES_SYMBOL", + "VALUE_SYMBOL", "WHERE_SYMBOL", "WORK_SYMBOL", "XOR_SYMBOL", "EQUAL_OPERATOR", + "ASSIGN_OPERATOR", "NULL_SAFE_EQUAL_OPERATOR", "GREATER_OR_EQUAL_OPERATOR", + "GREATER_THAN_OPERATOR", "LESS_OR_EQUAL_OPERATOR", "LESS_THAN_OPERATOR", + "NOT_EQUAL_OPERATOR", "PLUS_OPERATOR", "MINUS_OPERATOR", "MULT_OPERATOR", + "DIV_OPERATOR", "MOD_OPERATOR", "LOGICAL_NOT_OPERATOR", "BITWISE_NOT_OPERATOR", + "SHIFT_LEFT_OPERATOR", "SHIFT_RIGHT_OPERATOR", "LOGICAL_AND_OPERATOR", + "BITWISE_AND_OPERATOR", "BITWISE_XOR_OPERATOR", "LOGICAL_OR_OPERATOR", + "BITWISE_OR_OPERATOR", "DOT_SYMBOL", "COMMA_SYMBOL", "SEMICOLON_SYMBOL", + "COLON_SYMBOL", "OPEN_PAR_SYMBOL", "CLOSE_PAR_SYMBOL", "OPEN_CURLY_SYMBOL", + "CLOSE_CURLY_SYMBOL", "UNDERLINE_SYMBOL", "WHITESPACE", "IDENTIFIER", + "NCHAR_TEXT", "DOUBLE_QUOTED_TEXT", "SINGLE_QUOTED_TEXT", "BLOCK_COMMENT", + "POUND_COMMENT", "DASHDASH_COMMENT", "NOT_EQUAL2_OPERATOR" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -182,15 +184,16 @@ public ProgContext prog() { EnterRule(_localctx, 0, RULE_prog); int _la; try { - State = 100; + State = 102; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case Eof: EnterOuterAlt(_localctx, 1); { - State = 90; Match(Eof); + State = 92; Match(Eof); } break; + case SHOW_SYMBOL: case EXECFILE_SYMBOL: case QUIT_SYMBOL: case CREATE_SYMBOL: @@ -202,21 +205,21 @@ public ProgContext prog() { case OPEN_PAR_SYMBOL: EnterOuterAlt(_localctx, 2); { - State = 94; + State = 96; ErrorHandler.Sync(this); _la = TokenStream.LA(1); do { { { - State = 91; simpleStatement(); - State = 92; Match(SEMICOLON_SYMBOL); + State = 93; simpleStatement(); + State = 94; Match(SEMICOLON_SYMBOL); } } - State = 96; + State = 98; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - } while ( ((((_la - 6)) & ~0x3f) == 0 && ((1L << (_la - 6)) & ((1L << (EXECFILE_SYMBOL - 6)) | (1L << (QUIT_SYMBOL - 6)) | (1L << (CREATE_SYMBOL - 6)) | (1L << (DELETE_SYMBOL - 6)) | (1L << (DROP_SYMBOL - 6)) | (1L << (INSERT_SYMBOL - 6)) | (1L << (SELECT_SYMBOL - 6)) | (1L << (SEMICOLON_SYMBOL - 6)) | (1L << (OPEN_PAR_SYMBOL - 6)))) != 0) ); - State = 98; Match(Eof); + } while ( ((((_la - 6)) & ~0x3f) == 0 && ((1L << (_la - 6)) & ((1L << (SHOW_SYMBOL - 6)) | (1L << (EXECFILE_SYMBOL - 6)) | (1L << (QUIT_SYMBOL - 6)) | (1L << (CREATE_SYMBOL - 6)) | (1L << (DELETE_SYMBOL - 6)) | (1L << (DROP_SYMBOL - 6)) | (1L << (INSERT_SYMBOL - 6)) | (1L << (SELECT_SYMBOL - 6)) | (1L << (SEMICOLON_SYMBOL - 6)) | (1L << (OPEN_PAR_SYMBOL - 6)))) != 0) ); + State = 100; Match(Eof); } break; default: @@ -256,6 +259,9 @@ public QuitStatementContext quitStatement() { public ExecFileStatementContext execFileStatement() { return GetRuleContext(0); } + public ShowTablesStatementContext showTablesStatement() { + return GetRuleContext(0); + } public SimpleStatementContext(ParserRuleContext parent, int invokingState) : base(parent, invokingState) { @@ -281,7 +287,7 @@ public SimpleStatementContext simpleStatement() { SimpleStatementContext _localctx = new SimpleStatementContext(Context, State); EnterRule(_localctx, 2, RULE_simpleStatement); try { - State = 110; + State = 113; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case SEMICOLON_SYMBOL: @@ -292,44 +298,50 @@ public SimpleStatementContext simpleStatement() { case CREATE_SYMBOL: EnterOuterAlt(_localctx, 2); { - State = 103; createStatement(); + State = 105; createStatement(); } break; case DROP_SYMBOL: EnterOuterAlt(_localctx, 3); { - State = 104; dropStatement(); + State = 106; dropStatement(); } break; case DELETE_SYMBOL: EnterOuterAlt(_localctx, 4); { - State = 105; deleteStatement(); + State = 107; deleteStatement(); } break; case INSERT_SYMBOL: EnterOuterAlt(_localctx, 5); { - State = 106; insertStatement(); + State = 108; insertStatement(); } break; case SELECT_SYMBOL: case OPEN_PAR_SYMBOL: EnterOuterAlt(_localctx, 6); { - State = 107; selectStatement(); + State = 109; selectStatement(); } break; case QUIT_SYMBOL: EnterOuterAlt(_localctx, 7); { - State = 108; quitStatement(); + State = 110; quitStatement(); } break; case EXECFILE_SYMBOL: EnterOuterAlt(_localctx, 8); { - State = 109; execFileStatement(); + State = 111; execFileStatement(); + } + break; + case SHOW_SYMBOL: + EnterOuterAlt(_localctx, 9); + { + State = 112; showTablesStatement(); } break; default: @@ -376,7 +388,7 @@ public QuitStatementContext quitStatement() { try { EnterOuterAlt(_localctx, 1); { - State = 112; Match(QUIT_SYMBOL); + State = 115; Match(QUIT_SYMBOL); } } catch (RecognitionException re) { @@ -422,8 +434,8 @@ public ExecFileStatementContext execFileStatement() { try { EnterOuterAlt(_localctx, 1); { - State = 114; Match(EXECFILE_SYMBOL); - State = 115; + State = 117; Match(EXECFILE_SYMBOL); + State = 118; _la = TokenStream.LA(1); if ( !(_la==DOUBLE_QUOTED_TEXT || _la==SINGLE_QUOTED_TEXT) ) { ErrorHandler.RecoverInline(this); @@ -445,6 +457,51 @@ public ExecFileStatementContext execFileStatement() { return _localctx; } + public partial class ShowTablesStatementContext : ParserRuleContext { + public ITerminalNode SHOW_SYMBOL() { return GetToken(MiniSQLParser.SHOW_SYMBOL, 0); } + public ITerminalNode TABLES_SYMBOL() { return GetToken(MiniSQLParser.TABLES_SYMBOL, 0); } + public ShowTablesStatementContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_showTablesStatement; } } + public override void EnterRule(IParseTreeListener listener) { + IMiniSQLListener typedListener = listener as IMiniSQLListener; + if (typedListener != null) typedListener.EnterShowTablesStatement(this); + } + public override void ExitRule(IParseTreeListener listener) { + IMiniSQLListener typedListener = listener as IMiniSQLListener; + if (typedListener != null) typedListener.ExitShowTablesStatement(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IMiniSQLVisitor typedVisitor = visitor as IMiniSQLVisitor; + if (typedVisitor != null) return typedVisitor.VisitShowTablesStatement(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public ShowTablesStatementContext showTablesStatement() { + ShowTablesStatementContext _localctx = new ShowTablesStatementContext(Context, State); + EnterRule(_localctx, 8, RULE_showTablesStatement); + try { + EnterOuterAlt(_localctx, 1); + { + State = 120; Match(SHOW_SYMBOL); + State = 121; Match(TABLES_SYMBOL); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + public partial class CreateStatementContext : ParserRuleContext { public ITerminalNode CREATE_SYMBOL() { return GetToken(MiniSQLParser.CREATE_SYMBOL, 0); } public CreateTableContext createTable() { @@ -476,23 +533,23 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public CreateStatementContext createStatement() { CreateStatementContext _localctx = new CreateStatementContext(Context, State); - EnterRule(_localctx, 8, RULE_createStatement); + EnterRule(_localctx, 10, RULE_createStatement); try { EnterOuterAlt(_localctx, 1); { - State = 117; Match(CREATE_SYMBOL); - State = 120; + State = 123; Match(CREATE_SYMBOL); + State = 126; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case TABLE_SYMBOL: { - State = 118; createTable(); + State = 124; createTable(); } break; case INDEX_SYMBOL: case UNIQUE_SYMBOL: { - State = 119; createIndex(); + State = 125; createIndex(); } break; default: @@ -544,22 +601,22 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public CreateTableContext createTable() { CreateTableContext _localctx = new CreateTableContext(Context, State); - EnterRule(_localctx, 10, RULE_createTable); + EnterRule(_localctx, 12, RULE_createTable); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 122; Match(TABLE_SYMBOL); - State = 123; tableName(); + State = 128; Match(TABLE_SYMBOL); + State = 129; tableName(); { - State = 128; + State = 134; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==OPEN_PAR_SYMBOL) { { - State = 124; Match(OPEN_PAR_SYMBOL); - State = 125; tableElementList(); - State = 126; Match(CLOSE_PAR_SYMBOL); + State = 130; Match(OPEN_PAR_SYMBOL); + State = 131; tableElementList(); + State = 132; Match(CLOSE_PAR_SYMBOL); } } @@ -610,24 +667,24 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public CreateIndexContext createIndex() { CreateIndexContext _localctx = new CreateIndexContext(Context, State); - EnterRule(_localctx, 12, RULE_createIndex); + EnterRule(_localctx, 14, RULE_createIndex); int _la; try { EnterOuterAlt(_localctx, 1); { { - State = 131; + State = 137; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==UNIQUE_SYMBOL) { { - State = 130; Match(UNIQUE_SYMBOL); + State = 136; Match(UNIQUE_SYMBOL); } } - State = 133; _localctx.type = Match(INDEX_SYMBOL); - State = 134; indexName(); - State = 135; createIndexTarget(); + State = 139; _localctx.type = Match(INDEX_SYMBOL); + State = 140; indexName(); + State = 141; createIndexTarget(); } } } @@ -673,23 +730,23 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public DropStatementContext dropStatement() { DropStatementContext _localctx = new DropStatementContext(Context, State); - EnterRule(_localctx, 14, RULE_dropStatement); + EnterRule(_localctx, 16, RULE_dropStatement); try { EnterOuterAlt(_localctx, 1); { - State = 137; Match(DROP_SYMBOL); - State = 140; + State = 143; Match(DROP_SYMBOL); + State = 146; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case INDEX_SYMBOL: { - State = 138; dropIndex(); + State = 144; dropIndex(); } break; case TABLES_SYMBOL: case TABLE_SYMBOL: { - State = 139; dropTable(); + State = 145; dropTable(); } break; default: @@ -740,22 +797,22 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public DeleteStatementContext deleteStatement() { DeleteStatementContext _localctx = new DeleteStatementContext(Context, State); - EnterRule(_localctx, 16, RULE_deleteStatement); + EnterRule(_localctx, 18, RULE_deleteStatement); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 142; Match(DELETE_SYMBOL); + State = 148; Match(DELETE_SYMBOL); { - State = 143; Match(FROM_SYMBOL); + State = 149; Match(FROM_SYMBOL); { - State = 144; tableRef(); - State = 146; + State = 150; tableRef(); + State = 152; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==WHERE_SYMBOL) { { - State = 145; whereClause(); + State = 151; whereClause(); } } @@ -806,24 +863,24 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public InsertStatementContext insertStatement() { InsertStatementContext _localctx = new InsertStatementContext(Context, State); - EnterRule(_localctx, 18, RULE_insertStatement); + EnterRule(_localctx, 20, RULE_insertStatement); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 148; Match(INSERT_SYMBOL); - State = 150; + State = 154; Match(INSERT_SYMBOL); + State = 156; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==INTO_SYMBOL) { { - State = 149; Match(INTO_SYMBOL); + State = 155; Match(INTO_SYMBOL); } } - State = 152; tableRef(); + State = 158; tableRef(); { - State = 153; insertValues(); + State = 159; insertValues(); } } } @@ -868,21 +925,21 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public SelectStatementContext selectStatement() { SelectStatementContext _localctx = new SelectStatementContext(Context, State); - EnterRule(_localctx, 20, RULE_selectStatement); + EnterRule(_localctx, 22, RULE_selectStatement); try { - State = 157; + State = 163; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case SELECT_SYMBOL: EnterOuterAlt(_localctx, 1); { - State = 155; queryExpression(); + State = 161; queryExpression(); } break; case OPEN_PAR_SYMBOL: EnterOuterAlt(_localctx, 2); { - State = 156; queryExpressionParens(); + State = 162; queryExpressionParens(); } break; default: @@ -932,28 +989,28 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public QueryExpressionContext queryExpression() { QueryExpressionContext _localctx = new QueryExpressionContext(Context, State); - EnterRule(_localctx, 22, RULE_queryExpression); + EnterRule(_localctx, 24, RULE_queryExpression); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 159; Match(SELECT_SYMBOL); - State = 160; Match(MULT_OPERATOR); - State = 162; + State = 165; Match(SELECT_SYMBOL); + State = 166; Match(MULT_OPERATOR); + State = 168; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==FROM_SYMBOL) { { - State = 161; fromClause(); + State = 167; fromClause(); } } - State = 165; + State = 171; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==WHERE_SYMBOL) { { - State = 164; whereClause(); + State = 170; whereClause(); } } @@ -998,12 +1055,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public FromClauseContext fromClause() { FromClauseContext _localctx = new FromClauseContext(Context, State); - EnterRule(_localctx, 24, RULE_fromClause); + EnterRule(_localctx, 26, RULE_fromClause); try { EnterOuterAlt(_localctx, 1); { - State = 167; Match(FROM_SYMBOL); - State = 168; tableRef(); + State = 173; Match(FROM_SYMBOL); + State = 174; tableRef(); } } catch (RecognitionException re) { @@ -1049,28 +1106,28 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public QueryExpressionParensContext queryExpressionParens() { QueryExpressionParensContext _localctx = new QueryExpressionParensContext(Context, State); - EnterRule(_localctx, 26, RULE_queryExpressionParens); + EnterRule(_localctx, 28, RULE_queryExpressionParens); try { EnterOuterAlt(_localctx, 1); { - State = 170; Match(OPEN_PAR_SYMBOL); - State = 173; + State = 176; Match(OPEN_PAR_SYMBOL); + State = 179; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case OPEN_PAR_SYMBOL: { - State = 171; queryExpressionParens(); + State = 177; queryExpressionParens(); } break; case SELECT_SYMBOL: { - State = 172; queryExpression(); + State = 178; queryExpression(); } break; default: throw new NoViableAltException(this); } - State = 175; Match(CLOSE_PAR_SYMBOL); + State = 181; Match(CLOSE_PAR_SYMBOL); } } catch (RecognitionException re) { @@ -1117,20 +1174,20 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public DropIndexContext dropIndex() { DropIndexContext _localctx = new DropIndexContext(Context, State); - EnterRule(_localctx, 28, RULE_dropIndex); + EnterRule(_localctx, 30, RULE_dropIndex); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 177; _localctx.type = Match(INDEX_SYMBOL); - State = 178; indexRef(); - State = 181; + State = 183; _localctx.type = Match(INDEX_SYMBOL); + State = 184; indexRef(); + State = 187; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==ON_SYMBOL) { { - State = 179; Match(ON_SYMBOL); - State = 180; tableRef(); + State = 185; Match(ON_SYMBOL); + State = 186; tableRef(); } } @@ -1177,12 +1234,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public DropTableContext dropTable() { DropTableContext _localctx = new DropTableContext(Context, State); - EnterRule(_localctx, 30, RULE_dropTable); + EnterRule(_localctx, 32, RULE_dropTable); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 183; + State = 189; _localctx.type = TokenStream.LT(1); _la = TokenStream.LA(1); if ( !(_la==TABLES_SYMBOL || _la==TABLE_SYMBOL) ) { @@ -1192,7 +1249,7 @@ public DropTableContext dropTable() { ErrorHandler.ReportMatch(this); Consume(); } - State = 184; tableRef(); + State = 190; tableRef(); } } catch (RecognitionException re) { @@ -1235,12 +1292,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public InsertValuesContext insertValues() { InsertValuesContext _localctx = new InsertValuesContext(Context, State); - EnterRule(_localctx, 32, RULE_insertValues); + EnterRule(_localctx, 34, RULE_insertValues); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 186; + State = 192; _la = TokenStream.LA(1); if ( !(_la==VALUES_SYMBOL || _la==VALUE_SYMBOL) ) { ErrorHandler.RecoverInline(this); @@ -1249,7 +1306,7 @@ public InsertValuesContext insertValues() { ErrorHandler.ReportMatch(this); Consume(); } - State = 187; valueList(); + State = 193; valueList(); } } catch (RecognitionException re) { @@ -1292,22 +1349,22 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public ValueListContext valueList() { ValueListContext _localctx = new ValueListContext(Context, State); - EnterRule(_localctx, 34, RULE_valueList); + EnterRule(_localctx, 36, RULE_valueList); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 189; Match(OPEN_PAR_SYMBOL); - State = 191; + State = 195; Match(OPEN_PAR_SYMBOL); + State = 197; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INT_NUMBER) | (1L << DECIMAL_NUMBER) | (1L << NOT_SYMBOL) | (1L << PLUS_OPERATOR) | (1L << MINUS_OPERATOR))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (OPEN_PAR_SYMBOL - 65)) | (1L << (IDENTIFIER - 65)) | (1L << (DOUBLE_QUOTED_TEXT - 65)) | (1L << (SINGLE_QUOTED_TEXT - 65)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INT_NUMBER) | (1L << DECIMAL_NUMBER) | (1L << NOT_SYMBOL) | (1L << PLUS_OPERATOR) | (1L << MINUS_OPERATOR))) != 0) || ((((_la - 66)) & ~0x3f) == 0 && ((1L << (_la - 66)) & ((1L << (OPEN_PAR_SYMBOL - 66)) | (1L << (IDENTIFIER - 66)) | (1L << (DOUBLE_QUOTED_TEXT - 66)) | (1L << (SINGLE_QUOTED_TEXT - 66)))) != 0)) { { - State = 190; @values(); + State = 196; @values(); } } - State = 193; Match(CLOSE_PAR_SYMBOL); + State = 199; Match(CLOSE_PAR_SYMBOL); } } catch (RecognitionException re) { @@ -1355,27 +1412,27 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public ValuesContext @values() { ValuesContext _localctx = new ValuesContext(Context, State); - EnterRule(_localctx, 36, RULE_values); + EnterRule(_localctx, 38, RULE_values); int _la; try { EnterOuterAlt(_localctx, 1); { { - State = 195; expr(0); + State = 201; expr(0); } - State = 200; + State = 206; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==COMMA_SYMBOL) { { { - State = 196; Match(COMMA_SYMBOL); + State = 202; Match(COMMA_SYMBOL); { - State = 197; expr(0); + State = 203; expr(0); } } } - State = 202; + State = 208; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -1420,12 +1477,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public WhereClauseContext whereClause() { WhereClauseContext _localctx = new WhereClauseContext(Context, State); - EnterRule(_localctx, 38, RULE_whereClause); + EnterRule(_localctx, 40, RULE_whereClause); try { EnterOuterAlt(_localctx, 1); { - State = 203; Match(WHERE_SYMBOL); - State = 204; expr(0); + State = 209; Match(WHERE_SYMBOL); + State = 210; expr(0); } } catch (RecognitionException re) { @@ -1473,23 +1530,23 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public TableElementListContext tableElementList() { TableElementListContext _localctx = new TableElementListContext(Context, State); - EnterRule(_localctx, 40, RULE_tableElementList); + EnterRule(_localctx, 42, RULE_tableElementList); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 206; tableElement(); - State = 211; + State = 212; tableElement(); + State = 217; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==COMMA_SYMBOL) { { { - State = 207; Match(COMMA_SYMBOL); - State = 208; tableElement(); + State = 213; Match(COMMA_SYMBOL); + State = 214; tableElement(); } } - State = 213; + State = 219; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -1536,21 +1593,21 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public TableElementContext tableElement() { TableElementContext _localctx = new TableElementContext(Context, State); - EnterRule(_localctx, 42, RULE_tableElement); + EnterRule(_localctx, 44, RULE_tableElement); try { - State = 216; + State = 222; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case IDENTIFIER: EnterOuterAlt(_localctx, 1); { - State = 214; columnDefinition(); + State = 220; columnDefinition(); } break; case PRIMARY_SYMBOL: EnterOuterAlt(_localctx, 2); { - State = 215; tableConstraintDef(); + State = 221; tableConstraintDef(); } break; default: @@ -1598,15 +1655,15 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public TableConstraintDefContext tableConstraintDef() { TableConstraintDefContext _localctx = new TableConstraintDefContext(Context, State); - EnterRule(_localctx, 44, RULE_tableConstraintDef); + EnterRule(_localctx, 46, RULE_tableConstraintDef); try { EnterOuterAlt(_localctx, 1); { { - State = 218; _localctx.type = Match(PRIMARY_SYMBOL); - State = 219; Match(KEY_SYMBOL); + State = 224; _localctx.type = Match(PRIMARY_SYMBOL); + State = 225; Match(KEY_SYMBOL); } - State = 221; keyListVariants(); + State = 227; keyListVariants(); } } catch (RecognitionException re) { @@ -1650,12 +1707,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public ColumnDefinitionContext columnDefinition() { ColumnDefinitionContext _localctx = new ColumnDefinitionContext(Context, State); - EnterRule(_localctx, 46, RULE_columnDefinition); + EnterRule(_localctx, 48, RULE_columnDefinition); try { EnterOuterAlt(_localctx, 1); { - State = 223; columnName(); - State = 224; fieldDefinition(); + State = 229; columnName(); + State = 230; fieldDefinition(); } } catch (RecognitionException re) { @@ -1702,22 +1759,22 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public FieldDefinitionContext fieldDefinition() { FieldDefinitionContext _localctx = new FieldDefinitionContext(Context, State); - EnterRule(_localctx, 48, RULE_fieldDefinition); + EnterRule(_localctx, 50, RULE_fieldDefinition); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 226; dataType(); - State = 230; + State = 232; dataType(); + State = 236; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==UNIQUE_SYMBOL) { { { - State = 227; columnAttribute(); + State = 233; columnAttribute(); } } - State = 232; + State = 238; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -1765,34 +1822,34 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public DataTypeContext dataType() { DataTypeContext _localctx = new DataTypeContext(Context, State); - EnterRule(_localctx, 50, RULE_dataType); + EnterRule(_localctx, 52, RULE_dataType); int _la; try { - State = 239; + State = 245; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case INT_SYMBOL: EnterOuterAlt(_localctx, 1); { - State = 233; _localctx.type = Match(INT_SYMBOL); + State = 239; _localctx.type = Match(INT_SYMBOL); } break; case FLOAT_SYMBOL: EnterOuterAlt(_localctx, 2); { - State = 234; _localctx.type = Match(FLOAT_SYMBOL); + State = 240; _localctx.type = Match(FLOAT_SYMBOL); } break; case CHAR_SYMBOL: EnterOuterAlt(_localctx, 3); { - State = 235; _localctx.type = Match(CHAR_SYMBOL); - State = 237; + State = 241; _localctx.type = Match(CHAR_SYMBOL); + State = 243; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==OPEN_PAR_SYMBOL) { { - State = 236; fieldLength(); + State = 242; fieldLength(); } } @@ -1840,15 +1897,15 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public FieldLengthContext fieldLength() { FieldLengthContext _localctx = new FieldLengthContext(Context, State); - EnterRule(_localctx, 52, RULE_fieldLength); + EnterRule(_localctx, 54, RULE_fieldLength); try { EnterOuterAlt(_localctx, 1); { - State = 241; Match(OPEN_PAR_SYMBOL); + State = 247; Match(OPEN_PAR_SYMBOL); { - State = 242; Match(INT_NUMBER); + State = 248; Match(INT_NUMBER); } - State = 243; Match(CLOSE_PAR_SYMBOL); + State = 249; Match(CLOSE_PAR_SYMBOL); } } catch (RecognitionException re) { @@ -1889,18 +1946,18 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public ColumnAttributeContext columnAttribute() { ColumnAttributeContext _localctx = new ColumnAttributeContext(Context, State); - EnterRule(_localctx, 54, RULE_columnAttribute); + EnterRule(_localctx, 56, RULE_columnAttribute); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 245; _localctx.value = Match(UNIQUE_SYMBOL); - State = 247; + State = 251; _localctx.value = Match(UNIQUE_SYMBOL); + State = 253; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==KEY_SYMBOL) { { - State = 246; Match(KEY_SYMBOL); + State = 252; Match(KEY_SYMBOL); } } @@ -1948,13 +2005,13 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public CreateIndexTargetContext createIndexTarget() { CreateIndexTargetContext _localctx = new CreateIndexTargetContext(Context, State); - EnterRule(_localctx, 56, RULE_createIndexTarget); + EnterRule(_localctx, 58, RULE_createIndexTarget); try { EnterOuterAlt(_localctx, 1); { - State = 249; Match(ON_SYMBOL); - State = 250; tableRef(); - State = 251; keyListVariants(); + State = 255; Match(ON_SYMBOL); + State = 256; tableRef(); + State = 257; keyListVariants(); } } catch (RecognitionException re) { @@ -1997,13 +2054,13 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public KeyListVariantsContext keyListVariants() { KeyListVariantsContext _localctx = new KeyListVariantsContext(Context, State); - EnterRule(_localctx, 58, RULE_keyListVariants); + EnterRule(_localctx, 60, RULE_keyListVariants); try { EnterOuterAlt(_localctx, 1); { - State = 253; Match(OPEN_PAR_SYMBOL); - State = 254; keyPart(); - State = 255; Match(CLOSE_PAR_SYMBOL); + State = 259; Match(OPEN_PAR_SYMBOL); + State = 260; keyPart(); + State = 261; Match(CLOSE_PAR_SYMBOL); } } catch (RecognitionException re) { @@ -2044,11 +2101,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public TableNameContext tableName() { TableNameContext _localctx = new TableNameContext(Context, State); - EnterRule(_localctx, 60, RULE_tableName); + EnterRule(_localctx, 62, RULE_tableName); try { EnterOuterAlt(_localctx, 1); { - State = 257; qualifiedIdentifier(); + State = 263; qualifiedIdentifier(); } } catch (RecognitionException re) { @@ -2089,11 +2146,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public ColumnNameContext columnName() { ColumnNameContext _localctx = new ColumnNameContext(Context, State); - EnterRule(_localctx, 62, RULE_columnName); + EnterRule(_localctx, 64, RULE_columnName); try { EnterOuterAlt(_localctx, 1); { - State = 259; fieldIdentifier(); + State = 265; fieldIdentifier(); } } catch (RecognitionException re) { @@ -2134,11 +2191,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public KeyPartContext keyPart() { KeyPartContext _localctx = new KeyPartContext(Context, State); - EnterRule(_localctx, 64, RULE_keyPart); + EnterRule(_localctx, 66, RULE_keyPart); try { EnterOuterAlt(_localctx, 1); { - State = 261; identifier(); + State = 267; identifier(); } } catch (RecognitionException re) { @@ -2179,11 +2236,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public IndexRefContext indexRef() { IndexRefContext _localctx = new IndexRefContext(Context, State); - EnterRule(_localctx, 66, RULE_indexRef); + EnterRule(_localctx, 68, RULE_indexRef); try { EnterOuterAlt(_localctx, 1); { - State = 263; fieldIdentifier(); + State = 269; fieldIdentifier(); } } catch (RecognitionException re) { @@ -2224,11 +2281,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public TableRefContext tableRef() { TableRefContext _localctx = new TableRefContext(Context, State); - EnterRule(_localctx, 68, RULE_tableRef); + EnterRule(_localctx, 70, RULE_tableRef); try { EnterOuterAlt(_localctx, 1); { - State = 265; qualifiedIdentifier(); + State = 271; qualifiedIdentifier(); } } catch (RecognitionException re) { @@ -2269,11 +2326,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public FieldIdentifierContext fieldIdentifier() { FieldIdentifierContext _localctx = new FieldIdentifierContext(Context, State); - EnterRule(_localctx, 70, RULE_fieldIdentifier); + EnterRule(_localctx, 72, RULE_fieldIdentifier); try { EnterOuterAlt(_localctx, 1); { - State = 267; qualifiedIdentifier(); + State = 273; qualifiedIdentifier(); } } catch (RecognitionException re) { @@ -2314,11 +2371,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public IndexNameContext indexName() { IndexNameContext _localctx = new IndexNameContext(Context, State); - EnterRule(_localctx, 72, RULE_indexName); + EnterRule(_localctx, 74, RULE_indexName); try { EnterOuterAlt(_localctx, 1); { - State = 269; identifier(); + State = 275; identifier(); } } catch (RecognitionException re) { @@ -2357,12 +2414,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public PureIdentifierContext pureIdentifier() { PureIdentifierContext _localctx = new PureIdentifierContext(Context, State); - EnterRule(_localctx, 74, RULE_pureIdentifier); + EnterRule(_localctx, 76, RULE_pureIdentifier); try { EnterOuterAlt(_localctx, 1); { { - State = 271; Match(IDENTIFIER); + State = 277; Match(IDENTIFIER); } } } @@ -2404,11 +2461,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public IdentifierContext identifier() { IdentifierContext _localctx = new IdentifierContext(Context, State); - EnterRule(_localctx, 76, RULE_identifier); + EnterRule(_localctx, 78, RULE_identifier); try { EnterOuterAlt(_localctx, 1); { - State = 273; pureIdentifier(); + State = 279; pureIdentifier(); } } catch (RecognitionException re) { @@ -2449,11 +2506,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public QualifiedIdentifierContext qualifiedIdentifier() { QualifiedIdentifierContext _localctx = new QualifiedIdentifierContext(Context, State); - EnterRule(_localctx, 78, RULE_qualifiedIdentifier); + EnterRule(_localctx, 80, RULE_qualifiedIdentifier); try { EnterOuterAlt(_localctx, 1); { - State = 275; identifier(); + State = 281; identifier(); } } catch (RecognitionException re) { @@ -2720,14 +2777,14 @@ private ExprContext expr(int _p) { int _parentState = State; ExprContext _localctx = new ExprContext(Context, _parentState); ExprContext _prevctx = _localctx; - int _startState = 80; - EnterRecursionRule(_localctx, 80, RULE_expr, _p); + int _startState = 82; + EnterRecursionRule(_localctx, 82, RULE_expr, _p); int _la; try { int _alt; EnterOuterAlt(_localctx, 1); { - State = 287; + State = 293; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case OPEN_PAR_SYMBOL: @@ -2736,9 +2793,9 @@ private ExprContext expr(int _p) { Context = _localctx; _prevctx = _localctx; - State = 278; Match(OPEN_PAR_SYMBOL); - State = 279; expr(0); - State = 280; Match(CLOSE_PAR_SYMBOL); + State = 284; Match(OPEN_PAR_SYMBOL); + State = 285; expr(0); + State = 286; Match(CLOSE_PAR_SYMBOL); } break; case PLUS_OPERATOR: @@ -2747,7 +2804,7 @@ private ExprContext expr(int _p) { _localctx = new ExprSignContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 282; + State = 288; _la = TokenStream.LA(1); if ( !(_la==PLUS_OPERATOR || _la==MINUS_OPERATOR) ) { ErrorHandler.RecoverInline(this); @@ -2756,7 +2813,7 @@ private ExprContext expr(int _p) { ErrorHandler.ReportMatch(this); Consume(); } - State = 283; expr(9); + State = 289; expr(9); } break; case NOT_SYMBOL: @@ -2764,8 +2821,8 @@ private ExprContext expr(int _p) { _localctx = new ExprNotContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 284; Match(NOT_SYMBOL); - State = 285; expr(8); + State = 290; Match(NOT_SYMBOL); + State = 291; expr(8); } break; case INT_NUMBER: @@ -2777,14 +2834,14 @@ private ExprContext expr(int _p) { _localctx = new ExprAtomContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 286; atom(); + State = 292; atom(); } break; default: throw new NoViableAltException(this); } Context.Stop = TokenStream.LT(-1); - State = 310; + State = 316; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,24,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -2793,16 +2850,16 @@ private ExprContext expr(int _p) { TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 308; + State = 314; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,23,Context) ) { case 1: { _localctx = new ExprMulContext(new ExprContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_expr); - State = 289; + State = 295; if (!(Precpred(Context, 7))) throw new FailedPredicateException(this, "Precpred(Context, 7)"); - State = 290; + State = 296; ((ExprMulContext)_localctx).op = TokenStream.LT(1); _la = TokenStream.LA(1); if ( !(_la==MULT_OPERATOR || _la==DIV_OPERATOR) ) { @@ -2812,16 +2869,16 @@ private ExprContext expr(int _p) { ErrorHandler.ReportMatch(this); Consume(); } - State = 291; expr(8); + State = 297; expr(8); } break; case 2: { _localctx = new ExprAddContext(new ExprContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_expr); - State = 292; + State = 298; if (!(Precpred(Context, 6))) throw new FailedPredicateException(this, "Precpred(Context, 6)"); - State = 293; + State = 299; ((ExprAddContext)_localctx).op = TokenStream.LT(1); _la = TokenStream.LA(1); if ( !(_la==PLUS_OPERATOR || _la==MINUS_OPERATOR) ) { @@ -2831,26 +2888,26 @@ private ExprContext expr(int _p) { ErrorHandler.ReportMatch(this); Consume(); } - State = 294; expr(7); + State = 300; expr(7); } break; case 3: { _localctx = new ExprCompareContext(new ExprContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_expr); - State = 295; + State = 301; if (!(Precpred(Context, 5))) throw new FailedPredicateException(this, "Precpred(Context, 5)"); - State = 296; ((ExprCompareContext)_localctx).op = compOp(); - State = 297; expr(6); + State = 302; ((ExprCompareContext)_localctx).op = compOp(); + State = 303; expr(6); } break; case 4: { _localctx = new ExprAndContext(new ExprContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_expr); - State = 299; + State = 305; if (!(Precpred(Context, 4))) throw new FailedPredicateException(this, "Precpred(Context, 4)"); - State = 300; + State = 306; ((ExprAndContext)_localctx).op = TokenStream.LT(1); _la = TokenStream.LA(1); if ( !(_la==AND_SYMBOL || _la==LOGICAL_AND_OPERATOR) ) { @@ -2860,26 +2917,26 @@ private ExprContext expr(int _p) { ErrorHandler.ReportMatch(this); Consume(); } - State = 301; expr(5); + State = 307; expr(5); } break; case 5: { _localctx = new ExprXorContext(new ExprContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_expr); - State = 302; + State = 308; if (!(Precpred(Context, 3))) throw new FailedPredicateException(this, "Precpred(Context, 3)"); - State = 303; Match(XOR_SYMBOL); - State = 304; expr(4); + State = 309; Match(XOR_SYMBOL); + State = 310; expr(4); } break; case 6: { _localctx = new ExprOrContext(new ExprContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_expr); - State = 305; + State = 311; if (!(Precpred(Context, 2))) throw new FailedPredicateException(this, "Precpred(Context, 2)"); - State = 306; + State = 312; ((ExprOrContext)_localctx).op = TokenStream.LT(1); _la = TokenStream.LA(1); if ( !(_la==OR_SYMBOL || _la==LOGICAL_OR_OPERATOR) ) { @@ -2889,13 +2946,13 @@ private ExprContext expr(int _p) { ErrorHandler.ReportMatch(this); Consume(); } - State = 307; expr(3); + State = 313; expr(3); } break; } } } - State = 312; + State = 318; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,24,Context); } @@ -2942,12 +2999,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public CompOpContext compOp() { CompOpContext _localctx = new CompOpContext(Context, State); - EnterRule(_localctx, 82, RULE_compOp); + EnterRule(_localctx, 84, RULE_compOp); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 313; + State = 319; _la = TokenStream.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << EQUAL_OPERATOR) | (1L << GREATER_OR_EQUAL_OPERATOR) | (1L << GREATER_THAN_OPERATOR) | (1L << LESS_OR_EQUAL_OPERATOR) | (1L << LESS_THAN_OPERATOR) | (1L << NOT_EQUAL_OPERATOR))) != 0)) ) { ErrorHandler.RecoverInline(this); @@ -2999,9 +3056,9 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public AtomContext atom() { AtomContext _localctx = new AtomContext(Context, State); - EnterRule(_localctx, 84, RULE_atom); + EnterRule(_localctx, 86, RULE_atom); try { - State = 317; + State = 323; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case INT_NUMBER: @@ -3010,13 +3067,13 @@ public AtomContext atom() { case SINGLE_QUOTED_TEXT: EnterOuterAlt(_localctx, 1); { - State = 315; scientific(); + State = 321; scientific(); } break; case IDENTIFIER: EnterOuterAlt(_localctx, 2); { - State = 316; variable(); + State = 322; variable(); } break; default: @@ -3062,12 +3119,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public ScientificContext scientific() { ScientificContext _localctx = new ScientificContext(Context, State); - EnterRule(_localctx, 86, RULE_scientific); + EnterRule(_localctx, 88, RULE_scientific); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 319; + State = 325; _la = TokenStream.LA(1); if ( !(_la==INT_NUMBER || _la==DECIMAL_NUMBER || _la==DOUBLE_QUOTED_TEXT || _la==SINGLE_QUOTED_TEXT) ) { ErrorHandler.RecoverInline(this); @@ -3116,11 +3173,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public VariableContext variable() { VariableContext _localctx = new VariableContext(Context, State); - EnterRule(_localctx, 88, RULE_variable); + EnterRule(_localctx, 90, RULE_variable); try { EnterOuterAlt(_localctx, 1); { - State = 321; identifier(); + State = 327; identifier(); } } catch (RecognitionException re) { @@ -3136,7 +3193,7 @@ public VariableContext variable() { public override bool Sempred(RuleContext _localctx, int ruleIndex, int predIndex) { switch (ruleIndex) { - case 40: return expr_sempred((ExprContext)_localctx, predIndex); + case 41: return expr_sempred((ExprContext)_localctx, predIndex); } return true; } @@ -3154,7 +3211,7 @@ private bool expr_sempred(ExprContext _localctx, int predIndex) { private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x3', 'P', '\x146', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', + '\x5964', '\x3', 'Q', '\x14C', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', '\v', @@ -3170,250 +3227,255 @@ private bool expr_sempred(ExprContext _localctx, int predIndex) { '#', '\t', '#', '\x4', '$', '\t', '$', '\x4', '%', '\t', '%', '\x4', '&', '\t', '&', '\x4', '\'', '\t', '\'', '\x4', '(', '\t', '(', '\x4', ')', '\t', ')', '\x4', '*', '\t', '*', '\x4', '+', '\t', '+', '\x4', ',', '\t', - ',', '\x4', '-', '\t', '-', '\x4', '.', '\t', '.', '\x3', '\x2', '\x3', - '\x2', '\x3', '\x2', '\x3', '\x2', '\x6', '\x2', '\x61', '\n', '\x2', - '\r', '\x2', '\xE', '\x2', '\x62', '\x3', '\x2', '\x3', '\x2', '\x5', - '\x2', 'g', '\n', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', - '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x5', - '\x3', 'q', '\n', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', - '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x5', - '\x6', '{', '\n', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', - '\a', '\x3', '\a', '\x3', '\a', '\x5', '\a', '\x83', '\n', '\a', '\x3', - '\b', '\x5', '\b', '\x86', '\n', '\b', '\x3', '\b', '\x3', '\b', '\x3', - '\b', '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\t', '\x5', '\t', - '\x8F', '\n', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x3', '\n', - '\x5', '\n', '\x95', '\n', '\n', '\x3', '\v', '\x3', '\v', '\x5', '\v', - '\x99', '\n', '\v', '\x3', '\v', '\x3', '\v', '\x3', '\v', '\x3', '\f', - '\x3', '\f', '\x5', '\f', '\xA0', '\n', '\f', '\x3', '\r', '\x3', '\r', - '\x3', '\r', '\x5', '\r', '\xA5', '\n', '\r', '\x3', '\r', '\x5', '\r', - '\xA8', '\n', '\r', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xF', - '\x3', '\xF', '\x3', '\xF', '\x5', '\xF', '\xB0', '\n', '\xF', '\x3', - '\xF', '\x3', '\xF', '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', - '\x10', '\x5', '\x10', '\xB8', '\n', '\x10', '\x3', '\x11', '\x3', '\x11', - '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', - '\x3', '\x13', '\x5', '\x13', '\xC2', '\n', '\x13', '\x3', '\x13', '\x3', - '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', '\a', '\x14', '\xC9', - '\n', '\x14', '\f', '\x14', '\xE', '\x14', '\xCC', '\v', '\x14', '\x3', - '\x15', '\x3', '\x15', '\x3', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', - '\x16', '\a', '\x16', '\xD4', '\n', '\x16', '\f', '\x16', '\xE', '\x16', - '\xD7', '\v', '\x16', '\x3', '\x17', '\x3', '\x17', '\x5', '\x17', '\xDB', - '\n', '\x17', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', - '\x3', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', - '\x3', '\x1A', '\a', '\x1A', '\xE7', '\n', '\x1A', '\f', '\x1A', '\xE', - '\x1A', '\xEA', '\v', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1B', - '\x3', '\x1B', '\x5', '\x1B', '\xF0', '\n', '\x1B', '\x5', '\x1B', '\xF2', - '\n', '\x1B', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1C', - '\x3', '\x1D', '\x3', '\x1D', '\x5', '\x1D', '\xFA', '\n', '\x1D', '\x3', - '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1F', '\x3', - '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', '!', - '\x3', '!', '\x3', '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', '$', - '\x3', '$', '\x3', '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '\'', - '\x3', '\'', '\x3', '(', '\x3', '(', '\x3', ')', '\x3', ')', '\x3', '*', - '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', - '\x3', '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x122', '\n', '*', '\x3', - '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', - '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', - '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', - '*', '\a', '*', '\x137', '\n', '*', '\f', '*', '\xE', '*', '\x13A', '\v', - '*', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x5', ',', '\x140', - '\n', ',', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', '\x3', '.', - '\x2', '\x3', 'R', '/', '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', - '\x10', '\x12', '\x14', '\x16', '\x18', '\x1A', '\x1C', '\x1E', ' ', '\"', - '$', '&', '(', '*', ',', '.', '\x30', '\x32', '\x34', '\x36', '\x38', - ':', '<', '>', '@', '\x42', '\x44', '\x46', 'H', 'J', 'L', 'N', 'P', 'R', - 'T', 'V', 'X', 'Z', '\x2', '\v', '\x3', '\x2', 'K', 'L', '\x3', '\x2', - '!', '\"', '\x3', '\x2', '$', '%', '\x3', '\x2', '\x31', '\x32', '\x3', - '\x2', '\x33', '\x34', '\x4', '\x2', '\n', '\n', ':', ':', '\x4', '\x2', - '\x1E', '\x1E', '=', '=', '\x4', '\x2', ')', ')', ',', '\x30', '\x4', - '\x2', '\x5', '\x6', 'K', 'L', '\x2', '\x13F', '\x2', '\x66', '\x3', '\x2', - '\x2', '\x2', '\x4', 'p', '\x3', '\x2', '\x2', '\x2', '\x6', 'r', '\x3', - '\x2', '\x2', '\x2', '\b', 't', '\x3', '\x2', '\x2', '\x2', '\n', 'w', - '\x3', '\x2', '\x2', '\x2', '\f', '|', '\x3', '\x2', '\x2', '\x2', '\xE', - '\x85', '\x3', '\x2', '\x2', '\x2', '\x10', '\x8B', '\x3', '\x2', '\x2', - '\x2', '\x12', '\x90', '\x3', '\x2', '\x2', '\x2', '\x14', '\x96', '\x3', - '\x2', '\x2', '\x2', '\x16', '\x9F', '\x3', '\x2', '\x2', '\x2', '\x18', - '\xA1', '\x3', '\x2', '\x2', '\x2', '\x1A', '\xA9', '\x3', '\x2', '\x2', - '\x2', '\x1C', '\xAC', '\x3', '\x2', '\x2', '\x2', '\x1E', '\xB3', '\x3', - '\x2', '\x2', '\x2', ' ', '\xB9', '\x3', '\x2', '\x2', '\x2', '\"', '\xBC', - '\x3', '\x2', '\x2', '\x2', '$', '\xBF', '\x3', '\x2', '\x2', '\x2', '&', - '\xC5', '\x3', '\x2', '\x2', '\x2', '(', '\xCD', '\x3', '\x2', '\x2', - '\x2', '*', '\xD0', '\x3', '\x2', '\x2', '\x2', ',', '\xDA', '\x3', '\x2', - '\x2', '\x2', '.', '\xDC', '\x3', '\x2', '\x2', '\x2', '\x30', '\xE1', - '\x3', '\x2', '\x2', '\x2', '\x32', '\xE4', '\x3', '\x2', '\x2', '\x2', - '\x34', '\xF1', '\x3', '\x2', '\x2', '\x2', '\x36', '\xF3', '\x3', '\x2', - '\x2', '\x2', '\x38', '\xF7', '\x3', '\x2', '\x2', '\x2', ':', '\xFB', - '\x3', '\x2', '\x2', '\x2', '<', '\xFF', '\x3', '\x2', '\x2', '\x2', '>', - '\x103', '\x3', '\x2', '\x2', '\x2', '@', '\x105', '\x3', '\x2', '\x2', - '\x2', '\x42', '\x107', '\x3', '\x2', '\x2', '\x2', '\x44', '\x109', '\x3', - '\x2', '\x2', '\x2', '\x46', '\x10B', '\x3', '\x2', '\x2', '\x2', 'H', - '\x10D', '\x3', '\x2', '\x2', '\x2', 'J', '\x10F', '\x3', '\x2', '\x2', - '\x2', 'L', '\x111', '\x3', '\x2', '\x2', '\x2', 'N', '\x113', '\x3', - '\x2', '\x2', '\x2', 'P', '\x115', '\x3', '\x2', '\x2', '\x2', 'R', '\x121', - '\x3', '\x2', '\x2', '\x2', 'T', '\x13B', '\x3', '\x2', '\x2', '\x2', - 'V', '\x13F', '\x3', '\x2', '\x2', '\x2', 'X', '\x141', '\x3', '\x2', - '\x2', '\x2', 'Z', '\x143', '\x3', '\x2', '\x2', '\x2', '\\', 'g', '\a', - '\x2', '\x2', '\x3', ']', '^', '\x5', '\x4', '\x3', '\x2', '^', '_', '\a', - '\x41', '\x2', '\x2', '_', '\x61', '\x3', '\x2', '\x2', '\x2', '`', ']', - '\x3', '\x2', '\x2', '\x2', '\x61', '\x62', '\x3', '\x2', '\x2', '\x2', - '\x62', '`', '\x3', '\x2', '\x2', '\x2', '\x62', '\x63', '\x3', '\x2', - '\x2', '\x2', '\x63', '\x64', '\x3', '\x2', '\x2', '\x2', '\x64', '\x65', - '\a', '\x2', '\x2', '\x3', '\x65', 'g', '\x3', '\x2', '\x2', '\x2', '\x66', - '\\', '\x3', '\x2', '\x2', '\x2', '\x66', '`', '\x3', '\x2', '\x2', '\x2', - 'g', '\x3', '\x3', '\x2', '\x2', '\x2', 'h', 'q', '\x3', '\x2', '\x2', - '\x2', 'i', 'q', '\x5', '\n', '\x6', '\x2', 'j', 'q', '\x5', '\x10', '\t', - '\x2', 'k', 'q', '\x5', '\x12', '\n', '\x2', 'l', 'q', '\x5', '\x14', - '\v', '\x2', 'm', 'q', '\x5', '\x16', '\f', '\x2', 'n', 'q', '\x5', '\x6', - '\x4', '\x2', 'o', 'q', '\x5', '\b', '\x5', '\x2', 'p', 'h', '\x3', '\x2', - '\x2', '\x2', 'p', 'i', '\x3', '\x2', '\x2', '\x2', 'p', 'j', '\x3', '\x2', - '\x2', '\x2', 'p', 'k', '\x3', '\x2', '\x2', '\x2', 'p', 'l', '\x3', '\x2', - '\x2', '\x2', 'p', 'm', '\x3', '\x2', '\x2', '\x2', 'p', 'n', '\x3', '\x2', - '\x2', '\x2', 'p', 'o', '\x3', '\x2', '\x2', '\x2', 'q', '\x5', '\x3', - '\x2', '\x2', '\x2', 'r', 's', '\a', '\t', '\x2', '\x2', 's', '\a', '\x3', - '\x2', '\x2', '\x2', 't', 'u', '\a', '\b', '\x2', '\x2', 'u', 'v', '\t', - '\x2', '\x2', '\x2', 'v', '\t', '\x3', '\x2', '\x2', '\x2', 'w', 'z', - '\a', '\x10', '\x2', '\x2', 'x', '{', '\x5', '\f', '\a', '\x2', 'y', '{', - '\x5', '\xE', '\b', '\x2', 'z', 'x', '\x3', '\x2', '\x2', '\x2', 'z', - 'y', '\x3', '\x2', '\x2', '\x2', '{', '\v', '\x3', '\x2', '\x2', '\x2', - '|', '}', '\a', '\"', '\x2', '\x2', '}', '\x82', '\x5', '>', ' ', '\x2', - '~', '\x7F', '\a', '\x43', '\x2', '\x2', '\x7F', '\x80', '\x5', '*', '\x16', - '\x2', '\x80', '\x81', '\a', '\x44', '\x2', '\x2', '\x81', '\x83', '\x3', - '\x2', '\x2', '\x2', '\x82', '~', '\x3', '\x2', '\x2', '\x2', '\x82', - '\x83', '\x3', '\x2', '\x2', '\x2', '\x83', '\r', '\x3', '\x2', '\x2', - '\x2', '\x84', '\x86', '\a', '#', '\x2', '\x2', '\x85', '\x84', '\x3', - '\x2', '\x2', '\x2', '\x85', '\x86', '\x3', '\x2', '\x2', '\x2', '\x86', - '\x87', '\x3', '\x2', '\x2', '\x2', '\x87', '\x88', '\a', '\x16', '\x2', - '\x2', '\x88', '\x89', '\x5', 'J', '&', '\x2', '\x89', '\x8A', '\x5', - ':', '\x1E', '\x2', '\x8A', '\xF', '\x3', '\x2', '\x2', '\x2', '\x8B', - '\x8E', '\a', '\x13', '\x2', '\x2', '\x8C', '\x8F', '\x5', '\x1E', '\x10', - '\x2', '\x8D', '\x8F', '\x5', ' ', '\x11', '\x2', '\x8E', '\x8C', '\x3', - '\x2', '\x2', '\x2', '\x8E', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x8F', - '\x11', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\a', '\x11', '\x2', - '\x2', '\x91', '\x92', '\a', '\x15', '\x2', '\x2', '\x92', '\x94', '\x5', - '\x46', '$', '\x2', '\x93', '\x95', '\x5', '(', '\x15', '\x2', '\x94', - '\x93', '\x3', '\x2', '\x2', '\x2', '\x94', '\x95', '\x3', '\x2', '\x2', - '\x2', '\x95', '\x13', '\x3', '\x2', '\x2', '\x2', '\x96', '\x98', '\a', - '\x17', '\x2', '\x2', '\x97', '\x99', '\a', '\x18', '\x2', '\x2', '\x98', - '\x97', '\x3', '\x2', '\x2', '\x2', '\x98', '\x99', '\x3', '\x2', '\x2', - '\x2', '\x99', '\x9A', '\x3', '\x2', '\x2', '\x2', '\x9A', '\x9B', '\x5', - '\x46', '$', '\x2', '\x9B', '\x9C', '\x5', '\"', '\x12', '\x2', '\x9C', - '\x15', '\x3', '\x2', '\x2', '\x2', '\x9D', '\xA0', '\x5', '\x18', '\r', - '\x2', '\x9E', '\xA0', '\x5', '\x1C', '\xF', '\x2', '\x9F', '\x9D', '\x3', - '\x2', '\x2', '\x2', '\x9F', '\x9E', '\x3', '\x2', '\x2', '\x2', '\xA0', - '\x17', '\x3', '\x2', '\x2', '\x2', '\xA1', '\xA2', '\a', ' ', '\x2', - '\x2', '\xA2', '\xA4', '\a', '\x33', '\x2', '\x2', '\xA3', '\xA5', '\x5', - '\x1A', '\xE', '\x2', '\xA4', '\xA3', '\x3', '\x2', '\x2', '\x2', '\xA4', - '\xA5', '\x3', '\x2', '\x2', '\x2', '\xA5', '\xA7', '\x3', '\x2', '\x2', - '\x2', '\xA6', '\xA8', '\x5', '(', '\x15', '\x2', '\xA7', '\xA6', '\x3', - '\x2', '\x2', '\x2', '\xA7', '\xA8', '\x3', '\x2', '\x2', '\x2', '\xA8', - '\x19', '\x3', '\x2', '\x2', '\x2', '\xA9', '\xAA', '\a', '\x15', '\x2', - '\x2', '\xAA', '\xAB', '\x5', '\x46', '$', '\x2', '\xAB', '\x1B', '\x3', - '\x2', '\x2', '\x2', '\xAC', '\xAF', '\a', '\x43', '\x2', '\x2', '\xAD', - '\xB0', '\x5', '\x1C', '\xF', '\x2', '\xAE', '\xB0', '\x5', '\x18', '\r', - '\x2', '\xAF', '\xAD', '\x3', '\x2', '\x2', '\x2', '\xAF', '\xAE', '\x3', - '\x2', '\x2', '\x2', '\xB0', '\xB1', '\x3', '\x2', '\x2', '\x2', '\xB1', - '\xB2', '\a', '\x44', '\x2', '\x2', '\xB2', '\x1D', '\x3', '\x2', '\x2', - '\x2', '\xB3', '\xB4', '\a', '\x16', '\x2', '\x2', '\xB4', '\xB7', '\x5', - '\x44', '#', '\x2', '\xB5', '\xB6', '\a', '\x1C', '\x2', '\x2', '\xB6', - '\xB8', '\x5', '\x46', '$', '\x2', '\xB7', '\xB5', '\x3', '\x2', '\x2', - '\x2', '\xB7', '\xB8', '\x3', '\x2', '\x2', '\x2', '\xB8', '\x1F', '\x3', - '\x2', '\x2', '\x2', '\xB9', '\xBA', '\t', '\x3', '\x2', '\x2', '\xBA', - '\xBB', '\x5', '\x46', '$', '\x2', '\xBB', '!', '\x3', '\x2', '\x2', '\x2', - '\xBC', '\xBD', '\t', '\x4', '\x2', '\x2', '\xBD', '\xBE', '\x5', '$', - '\x13', '\x2', '\xBE', '#', '\x3', '\x2', '\x2', '\x2', '\xBF', '\xC1', - '\a', '\x43', '\x2', '\x2', '\xC0', '\xC2', '\x5', '&', '\x14', '\x2', - '\xC1', '\xC0', '\x3', '\x2', '\x2', '\x2', '\xC1', '\xC2', '\x3', '\x2', - '\x2', '\x2', '\xC2', '\xC3', '\x3', '\x2', '\x2', '\x2', '\xC3', '\xC4', - '\a', '\x44', '\x2', '\x2', '\xC4', '%', '\x3', '\x2', '\x2', '\x2', '\xC5', - '\xCA', '\x5', 'R', '*', '\x2', '\xC6', '\xC7', '\a', '@', '\x2', '\x2', - '\xC7', '\xC9', '\x5', 'R', '*', '\x2', '\xC8', '\xC6', '\x3', '\x2', - '\x2', '\x2', '\xC9', '\xCC', '\x3', '\x2', '\x2', '\x2', '\xCA', '\xC8', - '\x3', '\x2', '\x2', '\x2', '\xCA', '\xCB', '\x3', '\x2', '\x2', '\x2', - '\xCB', '\'', '\x3', '\x2', '\x2', '\x2', '\xCC', '\xCA', '\x3', '\x2', - '\x2', '\x2', '\xCD', '\xCE', '\a', '&', '\x2', '\x2', '\xCE', '\xCF', - '\x5', 'R', '*', '\x2', '\xCF', ')', '\x3', '\x2', '\x2', '\x2', '\xD0', - '\xD5', '\x5', ',', '\x17', '\x2', '\xD1', '\xD2', '\a', '@', '\x2', '\x2', - '\xD2', '\xD4', '\x5', ',', '\x17', '\x2', '\xD3', '\xD1', '\x3', '\x2', - '\x2', '\x2', '\xD4', '\xD7', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD3', - '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD6', '\x3', '\x2', '\x2', '\x2', - '\xD6', '+', '\x3', '\x2', '\x2', '\x2', '\xD7', '\xD5', '\x3', '\x2', - '\x2', '\x2', '\xD8', '\xDB', '\x5', '\x30', '\x19', '\x2', '\xD9', '\xDB', - '\x5', '.', '\x18', '\x2', '\xDA', '\xD8', '\x3', '\x2', '\x2', '\x2', - '\xDA', '\xD9', '\x3', '\x2', '\x2', '\x2', '\xDB', '-', '\x3', '\x2', - '\x2', '\x2', '\xDC', '\xDD', '\a', '\x1F', '\x2', '\x2', '\xDD', '\xDE', - '\a', '\x1A', '\x2', '\x2', '\xDE', '\xDF', '\x3', '\x2', '\x2', '\x2', - '\xDF', '\xE0', '\x5', '<', '\x1F', '\x2', '\xE0', '/', '\x3', '\x2', - '\x2', '\x2', '\xE1', '\xE2', '\x5', '@', '!', '\x2', '\xE2', '\xE3', - '\x5', '\x32', '\x1A', '\x2', '\xE3', '\x31', '\x3', '\x2', '\x2', '\x2', - '\xE4', '\xE8', '\x5', '\x34', '\x1B', '\x2', '\xE5', '\xE7', '\x5', '\x38', - '\x1D', '\x2', '\xE6', '\xE5', '\x3', '\x2', '\x2', '\x2', '\xE7', '\xEA', - '\x3', '\x2', '\x2', '\x2', '\xE8', '\xE6', '\x3', '\x2', '\x2', '\x2', - '\xE8', '\xE9', '\x3', '\x2', '\x2', '\x2', '\xE9', '\x33', '\x3', '\x2', - '\x2', '\x2', '\xEA', '\xE8', '\x3', '\x2', '\x2', '\x2', '\xEB', '\xF2', - '\a', '\x19', '\x2', '\x2', '\xEC', '\xF2', '\a', '\x14', '\x2', '\x2', - '\xED', '\xEF', '\a', '\xF', '\x2', '\x2', '\xEE', '\xF0', '\x5', '\x36', - '\x1C', '\x2', '\xEF', '\xEE', '\x3', '\x2', '\x2', '\x2', '\xEF', '\xF0', - '\x3', '\x2', '\x2', '\x2', '\xF0', '\xF2', '\x3', '\x2', '\x2', '\x2', - '\xF1', '\xEB', '\x3', '\x2', '\x2', '\x2', '\xF1', '\xEC', '\x3', '\x2', - '\x2', '\x2', '\xF1', '\xED', '\x3', '\x2', '\x2', '\x2', '\xF2', '\x35', - '\x3', '\x2', '\x2', '\x2', '\xF3', '\xF4', '\a', '\x43', '\x2', '\x2', - '\xF4', '\xF5', '\a', '\x5', '\x2', '\x2', '\xF5', '\xF6', '\a', '\x44', - '\x2', '\x2', '\xF6', '\x37', '\x3', '\x2', '\x2', '\x2', '\xF7', '\xF9', - '\a', '#', '\x2', '\x2', '\xF8', '\xFA', '\a', '\x1A', '\x2', '\x2', '\xF9', - '\xF8', '\x3', '\x2', '\x2', '\x2', '\xF9', '\xFA', '\x3', '\x2', '\x2', - '\x2', '\xFA', '\x39', '\x3', '\x2', '\x2', '\x2', '\xFB', '\xFC', '\a', - '\x1C', '\x2', '\x2', '\xFC', '\xFD', '\x5', '\x46', '$', '\x2', '\xFD', - '\xFE', '\x5', '<', '\x1F', '\x2', '\xFE', ';', '\x3', '\x2', '\x2', '\x2', - '\xFF', '\x100', '\a', '\x43', '\x2', '\x2', '\x100', '\x101', '\x5', - '\x42', '\"', '\x2', '\x101', '\x102', '\a', '\x44', '\x2', '\x2', '\x102', - '=', '\x3', '\x2', '\x2', '\x2', '\x103', '\x104', '\x5', 'P', ')', '\x2', - '\x104', '?', '\x3', '\x2', '\x2', '\x2', '\x105', '\x106', '\x5', 'H', - '%', '\x2', '\x106', '\x41', '\x3', '\x2', '\x2', '\x2', '\x107', '\x108', - '\x5', 'N', '(', '\x2', '\x108', '\x43', '\x3', '\x2', '\x2', '\x2', '\x109', - '\x10A', '\x5', 'H', '%', '\x2', '\x10A', '\x45', '\x3', '\x2', '\x2', - '\x2', '\x10B', '\x10C', '\x5', 'P', ')', '\x2', '\x10C', 'G', '\x3', - '\x2', '\x2', '\x2', '\x10D', '\x10E', '\x5', 'P', ')', '\x2', '\x10E', - 'I', '\x3', '\x2', '\x2', '\x2', '\x10F', '\x110', '\x5', 'N', '(', '\x2', - '\x110', 'K', '\x3', '\x2', '\x2', '\x2', '\x111', '\x112', '\a', 'I', - '\x2', '\x2', '\x112', 'M', '\x3', '\x2', '\x2', '\x2', '\x113', '\x114', - '\x5', 'L', '\'', '\x2', '\x114', 'O', '\x3', '\x2', '\x2', '\x2', '\x115', - '\x116', '\x5', 'N', '(', '\x2', '\x116', 'Q', '\x3', '\x2', '\x2', '\x2', - '\x117', '\x118', '\b', '*', '\x1', '\x2', '\x118', '\x119', '\a', '\x43', - '\x2', '\x2', '\x119', '\x11A', '\x5', 'R', '*', '\x2', '\x11A', '\x11B', - '\a', '\x44', '\x2', '\x2', '\x11B', '\x122', '\x3', '\x2', '\x2', '\x2', - '\x11C', '\x11D', '\t', '\x5', '\x2', '\x2', '\x11D', '\x122', '\x5', - 'R', '*', '\v', '\x11E', '\x11F', '\a', '\x1B', '\x2', '\x2', '\x11F', - '\x122', '\x5', 'R', '*', '\n', '\x120', '\x122', '\x5', 'V', ',', '\x2', - '\x121', '\x117', '\x3', '\x2', '\x2', '\x2', '\x121', '\x11C', '\x3', - '\x2', '\x2', '\x2', '\x121', '\x11E', '\x3', '\x2', '\x2', '\x2', '\x121', - '\x120', '\x3', '\x2', '\x2', '\x2', '\x122', '\x138', '\x3', '\x2', '\x2', - '\x2', '\x123', '\x124', '\f', '\t', '\x2', '\x2', '\x124', '\x125', '\t', - '\x6', '\x2', '\x2', '\x125', '\x137', '\x5', 'R', '*', '\n', '\x126', - '\x127', '\f', '\b', '\x2', '\x2', '\x127', '\x128', '\t', '\x5', '\x2', - '\x2', '\x128', '\x137', '\x5', 'R', '*', '\t', '\x129', '\x12A', '\f', - '\a', '\x2', '\x2', '\x12A', '\x12B', '\x5', 'T', '+', '\x2', '\x12B', - '\x12C', '\x5', 'R', '*', '\b', '\x12C', '\x137', '\x3', '\x2', '\x2', - '\x2', '\x12D', '\x12E', '\f', '\x6', '\x2', '\x2', '\x12E', '\x12F', - '\t', '\a', '\x2', '\x2', '\x12F', '\x137', '\x5', 'R', '*', '\a', '\x130', - '\x131', '\f', '\x5', '\x2', '\x2', '\x131', '\x132', '\a', '(', '\x2', - '\x2', '\x132', '\x137', '\x5', 'R', '*', '\x6', '\x133', '\x134', '\f', - '\x4', '\x2', '\x2', '\x134', '\x135', '\t', '\b', '\x2', '\x2', '\x135', - '\x137', '\x5', 'R', '*', '\x5', '\x136', '\x123', '\x3', '\x2', '\x2', - '\x2', '\x136', '\x126', '\x3', '\x2', '\x2', '\x2', '\x136', '\x129', - '\x3', '\x2', '\x2', '\x2', '\x136', '\x12D', '\x3', '\x2', '\x2', '\x2', - '\x136', '\x130', '\x3', '\x2', '\x2', '\x2', '\x136', '\x133', '\x3', - '\x2', '\x2', '\x2', '\x137', '\x13A', '\x3', '\x2', '\x2', '\x2', '\x138', - '\x136', '\x3', '\x2', '\x2', '\x2', '\x138', '\x139', '\x3', '\x2', '\x2', - '\x2', '\x139', 'S', '\x3', '\x2', '\x2', '\x2', '\x13A', '\x138', '\x3', - '\x2', '\x2', '\x2', '\x13B', '\x13C', '\t', '\t', '\x2', '\x2', '\x13C', - 'U', '\x3', '\x2', '\x2', '\x2', '\x13D', '\x140', '\x5', 'X', '-', '\x2', - '\x13E', '\x140', '\x5', 'Z', '.', '\x2', '\x13F', '\x13D', '\x3', '\x2', - '\x2', '\x2', '\x13F', '\x13E', '\x3', '\x2', '\x2', '\x2', '\x140', 'W', - '\x3', '\x2', '\x2', '\x2', '\x141', '\x142', '\t', '\n', '\x2', '\x2', - '\x142', 'Y', '\x3', '\x2', '\x2', '\x2', '\x143', '\x144', '\x5', 'N', - '(', '\x2', '\x144', '[', '\x3', '\x2', '\x2', '\x2', '\x1C', '\x62', - '\x66', 'p', 'z', '\x82', '\x85', '\x8E', '\x94', '\x98', '\x9F', '\xA4', - '\xA7', '\xAF', '\xB7', '\xC1', '\xCA', '\xD5', '\xDA', '\xE8', '\xEF', - '\xF1', '\xF9', '\x121', '\x136', '\x138', '\x13F', + ',', '\x4', '-', '\t', '-', '\x4', '.', '\t', '.', '\x4', '/', '\t', '/', + '\x3', '\x2', '\x3', '\x2', '\x3', '\x2', '\x3', '\x2', '\x6', '\x2', + '\x63', '\n', '\x2', '\r', '\x2', '\xE', '\x2', '\x64', '\x3', '\x2', + '\x3', '\x2', '\x5', '\x2', 'i', '\n', '\x2', '\x3', '\x3', '\x3', '\x3', + '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', + '\x3', '\x3', '\x3', '\x3', '\x5', '\x3', 't', '\n', '\x3', '\x3', '\x4', + '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', + '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x5', + '\a', '\x81', '\n', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\b', '\x3', + '\b', '\x3', '\b', '\x3', '\b', '\x5', '\b', '\x89', '\n', '\b', '\x3', + '\t', '\x5', '\t', '\x8C', '\n', '\t', '\x3', '\t', '\x3', '\t', '\x3', + '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x5', '\n', + '\x95', '\n', '\n', '\x3', '\v', '\x3', '\v', '\x3', '\v', '\x3', '\v', + '\x5', '\v', '\x9B', '\n', '\v', '\x3', '\f', '\x3', '\f', '\x5', '\f', + '\x9F', '\n', '\f', '\x3', '\f', '\x3', '\f', '\x3', '\f', '\x3', '\r', + '\x3', '\r', '\x5', '\r', '\xA6', '\n', '\r', '\x3', '\xE', '\x3', '\xE', + '\x3', '\xE', '\x5', '\xE', '\xAB', '\n', '\xE', '\x3', '\xE', '\x5', + '\xE', '\xAE', '\n', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', + '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x5', '\x10', '\xB6', '\n', + '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x11', '\x3', '\x11', '\x3', + '\x11', '\x3', '\x11', '\x5', '\x11', '\xBE', '\n', '\x11', '\x3', '\x12', + '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x3', '\x13', '\x3', '\x13', + '\x3', '\x14', '\x3', '\x14', '\x5', '\x14', '\xC8', '\n', '\x14', '\x3', + '\x14', '\x3', '\x14', '\x3', '\x15', '\x3', '\x15', '\x3', '\x15', '\a', + '\x15', '\xCF', '\n', '\x15', '\f', '\x15', '\xE', '\x15', '\xD2', '\v', + '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', '\x3', + '\x17', '\x3', '\x17', '\a', '\x17', '\xDA', '\n', '\x17', '\f', '\x17', + '\xE', '\x17', '\xDD', '\v', '\x17', '\x3', '\x18', '\x3', '\x18', '\x5', + '\x18', '\xE1', '\n', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', + '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1A', + '\x3', '\x1B', '\x3', '\x1B', '\a', '\x1B', '\xED', '\n', '\x1B', '\f', + '\x1B', '\xE', '\x1B', '\xF0', '\v', '\x1B', '\x3', '\x1C', '\x3', '\x1C', + '\x3', '\x1C', '\x3', '\x1C', '\x5', '\x1C', '\xF6', '\n', '\x1C', '\x5', + '\x1C', '\xF8', '\n', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', + '\x3', '\x1D', '\x3', '\x1E', '\x3', '\x1E', '\x5', '\x1E', '\x100', '\n', + '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', + ' ', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', '!', '\x3', '!', '\x3', + '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', '$', '\x3', '$', '\x3', + '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '\'', '\x3', '\'', '\x3', + '(', '\x3', '(', '\x3', ')', '\x3', ')', '\x3', '*', '\x3', '*', '\x3', + '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', + '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x5', '+', '\x128', '\n', '+', + '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', + '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', + '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', + '\x3', '+', '\a', '+', '\x13D', '\n', '+', '\f', '+', '\xE', '+', '\x140', + '\v', '+', '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x5', '-', + '\x146', '\n', '-', '\x3', '.', '\x3', '.', '\x3', '/', '\x3', '/', '\x3', + '/', '\x2', '\x3', 'T', '\x30', '\x2', '\x4', '\x6', '\b', '\n', '\f', + '\xE', '\x10', '\x12', '\x14', '\x16', '\x18', '\x1A', '\x1C', '\x1E', + ' ', '\"', '$', '&', '(', '*', ',', '.', '\x30', '\x32', '\x34', '\x36', + '\x38', ':', '<', '>', '@', '\x42', '\x44', '\x46', 'H', 'J', 'L', 'N', + 'P', 'R', 'T', 'V', 'X', 'Z', '\\', '\x2', '\v', '\x3', '\x2', 'L', 'M', + '\x3', '\x2', '\"', '#', '\x3', '\x2', '%', '&', '\x3', '\x2', '\x32', + '\x33', '\x3', '\x2', '\x34', '\x35', '\x4', '\x2', '\v', '\v', ';', ';', + '\x4', '\x2', '\x1F', '\x1F', '>', '>', '\x4', '\x2', '*', '*', '-', '\x31', + '\x4', '\x2', '\x5', '\x6', 'L', 'M', '\x2', '\x145', '\x2', 'h', '\x3', + '\x2', '\x2', '\x2', '\x4', 's', '\x3', '\x2', '\x2', '\x2', '\x6', 'u', + '\x3', '\x2', '\x2', '\x2', '\b', 'w', '\x3', '\x2', '\x2', '\x2', '\n', + 'z', '\x3', '\x2', '\x2', '\x2', '\f', '}', '\x3', '\x2', '\x2', '\x2', + '\xE', '\x82', '\x3', '\x2', '\x2', '\x2', '\x10', '\x8B', '\x3', '\x2', + '\x2', '\x2', '\x12', '\x91', '\x3', '\x2', '\x2', '\x2', '\x14', '\x96', + '\x3', '\x2', '\x2', '\x2', '\x16', '\x9C', '\x3', '\x2', '\x2', '\x2', + '\x18', '\xA5', '\x3', '\x2', '\x2', '\x2', '\x1A', '\xA7', '\x3', '\x2', + '\x2', '\x2', '\x1C', '\xAF', '\x3', '\x2', '\x2', '\x2', '\x1E', '\xB2', + '\x3', '\x2', '\x2', '\x2', ' ', '\xB9', '\x3', '\x2', '\x2', '\x2', '\"', + '\xBF', '\x3', '\x2', '\x2', '\x2', '$', '\xC2', '\x3', '\x2', '\x2', + '\x2', '&', '\xC5', '\x3', '\x2', '\x2', '\x2', '(', '\xCB', '\x3', '\x2', + '\x2', '\x2', '*', '\xD3', '\x3', '\x2', '\x2', '\x2', ',', '\xD6', '\x3', + '\x2', '\x2', '\x2', '.', '\xE0', '\x3', '\x2', '\x2', '\x2', '\x30', + '\xE2', '\x3', '\x2', '\x2', '\x2', '\x32', '\xE7', '\x3', '\x2', '\x2', + '\x2', '\x34', '\xEA', '\x3', '\x2', '\x2', '\x2', '\x36', '\xF7', '\x3', + '\x2', '\x2', '\x2', '\x38', '\xF9', '\x3', '\x2', '\x2', '\x2', ':', + '\xFD', '\x3', '\x2', '\x2', '\x2', '<', '\x101', '\x3', '\x2', '\x2', + '\x2', '>', '\x105', '\x3', '\x2', '\x2', '\x2', '@', '\x109', '\x3', + '\x2', '\x2', '\x2', '\x42', '\x10B', '\x3', '\x2', '\x2', '\x2', '\x44', + '\x10D', '\x3', '\x2', '\x2', '\x2', '\x46', '\x10F', '\x3', '\x2', '\x2', + '\x2', 'H', '\x111', '\x3', '\x2', '\x2', '\x2', 'J', '\x113', '\x3', + '\x2', '\x2', '\x2', 'L', '\x115', '\x3', '\x2', '\x2', '\x2', 'N', '\x117', + '\x3', '\x2', '\x2', '\x2', 'P', '\x119', '\x3', '\x2', '\x2', '\x2', + 'R', '\x11B', '\x3', '\x2', '\x2', '\x2', 'T', '\x127', '\x3', '\x2', + '\x2', '\x2', 'V', '\x141', '\x3', '\x2', '\x2', '\x2', 'X', '\x145', + '\x3', '\x2', '\x2', '\x2', 'Z', '\x147', '\x3', '\x2', '\x2', '\x2', + '\\', '\x149', '\x3', '\x2', '\x2', '\x2', '^', 'i', '\a', '\x2', '\x2', + '\x3', '_', '`', '\x5', '\x4', '\x3', '\x2', '`', '\x61', '\a', '\x42', + '\x2', '\x2', '\x61', '\x63', '\x3', '\x2', '\x2', '\x2', '\x62', '_', + '\x3', '\x2', '\x2', '\x2', '\x63', '\x64', '\x3', '\x2', '\x2', '\x2', + '\x64', '\x62', '\x3', '\x2', '\x2', '\x2', '\x64', '\x65', '\x3', '\x2', + '\x2', '\x2', '\x65', '\x66', '\x3', '\x2', '\x2', '\x2', '\x66', 'g', + '\a', '\x2', '\x2', '\x3', 'g', 'i', '\x3', '\x2', '\x2', '\x2', 'h', + '^', '\x3', '\x2', '\x2', '\x2', 'h', '\x62', '\x3', '\x2', '\x2', '\x2', + 'i', '\x3', '\x3', '\x2', '\x2', '\x2', 'j', 't', '\x3', '\x2', '\x2', + '\x2', 'k', 't', '\x5', '\f', '\a', '\x2', 'l', 't', '\x5', '\x12', '\n', + '\x2', 'm', 't', '\x5', '\x14', '\v', '\x2', 'n', 't', '\x5', '\x16', + '\f', '\x2', 'o', 't', '\x5', '\x18', '\r', '\x2', 'p', 't', '\x5', '\x6', + '\x4', '\x2', 'q', 't', '\x5', '\b', '\x5', '\x2', 'r', 't', '\x5', '\n', + '\x6', '\x2', 's', 'j', '\x3', '\x2', '\x2', '\x2', 's', 'k', '\x3', '\x2', + '\x2', '\x2', 's', 'l', '\x3', '\x2', '\x2', '\x2', 's', 'm', '\x3', '\x2', + '\x2', '\x2', 's', 'n', '\x3', '\x2', '\x2', '\x2', 's', 'o', '\x3', '\x2', + '\x2', '\x2', 's', 'p', '\x3', '\x2', '\x2', '\x2', 's', 'q', '\x3', '\x2', + '\x2', '\x2', 's', 'r', '\x3', '\x2', '\x2', '\x2', 't', '\x5', '\x3', + '\x2', '\x2', '\x2', 'u', 'v', '\a', '\n', '\x2', '\x2', 'v', '\a', '\x3', + '\x2', '\x2', '\x2', 'w', 'x', '\a', '\t', '\x2', '\x2', 'x', 'y', '\t', + '\x2', '\x2', '\x2', 'y', '\t', '\x3', '\x2', '\x2', '\x2', 'z', '{', + '\a', '\b', '\x2', '\x2', '{', '|', '\a', '\"', '\x2', '\x2', '|', '\v', + '\x3', '\x2', '\x2', '\x2', '}', '\x80', '\a', '\x11', '\x2', '\x2', '~', + '\x81', '\x5', '\xE', '\b', '\x2', '\x7F', '\x81', '\x5', '\x10', '\t', + '\x2', '\x80', '~', '\x3', '\x2', '\x2', '\x2', '\x80', '\x7F', '\x3', + '\x2', '\x2', '\x2', '\x81', '\r', '\x3', '\x2', '\x2', '\x2', '\x82', + '\x83', '\a', '#', '\x2', '\x2', '\x83', '\x88', '\x5', '@', '!', '\x2', + '\x84', '\x85', '\a', '\x44', '\x2', '\x2', '\x85', '\x86', '\x5', ',', + '\x17', '\x2', '\x86', '\x87', '\a', '\x45', '\x2', '\x2', '\x87', '\x89', + '\x3', '\x2', '\x2', '\x2', '\x88', '\x84', '\x3', '\x2', '\x2', '\x2', + '\x88', '\x89', '\x3', '\x2', '\x2', '\x2', '\x89', '\xF', '\x3', '\x2', + '\x2', '\x2', '\x8A', '\x8C', '\a', '$', '\x2', '\x2', '\x8B', '\x8A', + '\x3', '\x2', '\x2', '\x2', '\x8B', '\x8C', '\x3', '\x2', '\x2', '\x2', + '\x8C', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x8D', '\x8E', '\a', '\x17', + '\x2', '\x2', '\x8E', '\x8F', '\x5', 'L', '\'', '\x2', '\x8F', '\x90', + '\x5', '<', '\x1F', '\x2', '\x90', '\x11', '\x3', '\x2', '\x2', '\x2', + '\x91', '\x94', '\a', '\x14', '\x2', '\x2', '\x92', '\x95', '\x5', ' ', + '\x11', '\x2', '\x93', '\x95', '\x5', '\"', '\x12', '\x2', '\x94', '\x92', + '\x3', '\x2', '\x2', '\x2', '\x94', '\x93', '\x3', '\x2', '\x2', '\x2', + '\x95', '\x13', '\x3', '\x2', '\x2', '\x2', '\x96', '\x97', '\a', '\x12', + '\x2', '\x2', '\x97', '\x98', '\a', '\x16', '\x2', '\x2', '\x98', '\x9A', + '\x5', 'H', '%', '\x2', '\x99', '\x9B', '\x5', '*', '\x16', '\x2', '\x9A', + '\x99', '\x3', '\x2', '\x2', '\x2', '\x9A', '\x9B', '\x3', '\x2', '\x2', + '\x2', '\x9B', '\x15', '\x3', '\x2', '\x2', '\x2', '\x9C', '\x9E', '\a', + '\x18', '\x2', '\x2', '\x9D', '\x9F', '\a', '\x19', '\x2', '\x2', '\x9E', + '\x9D', '\x3', '\x2', '\x2', '\x2', '\x9E', '\x9F', '\x3', '\x2', '\x2', + '\x2', '\x9F', '\xA0', '\x3', '\x2', '\x2', '\x2', '\xA0', '\xA1', '\x5', + 'H', '%', '\x2', '\xA1', '\xA2', '\x5', '$', '\x13', '\x2', '\xA2', '\x17', + '\x3', '\x2', '\x2', '\x2', '\xA3', '\xA6', '\x5', '\x1A', '\xE', '\x2', + '\xA4', '\xA6', '\x5', '\x1E', '\x10', '\x2', '\xA5', '\xA3', '\x3', '\x2', + '\x2', '\x2', '\xA5', '\xA4', '\x3', '\x2', '\x2', '\x2', '\xA6', '\x19', + '\x3', '\x2', '\x2', '\x2', '\xA7', '\xA8', '\a', '!', '\x2', '\x2', '\xA8', + '\xAA', '\a', '\x34', '\x2', '\x2', '\xA9', '\xAB', '\x5', '\x1C', '\xF', + '\x2', '\xAA', '\xA9', '\x3', '\x2', '\x2', '\x2', '\xAA', '\xAB', '\x3', + '\x2', '\x2', '\x2', '\xAB', '\xAD', '\x3', '\x2', '\x2', '\x2', '\xAC', + '\xAE', '\x5', '*', '\x16', '\x2', '\xAD', '\xAC', '\x3', '\x2', '\x2', + '\x2', '\xAD', '\xAE', '\x3', '\x2', '\x2', '\x2', '\xAE', '\x1B', '\x3', + '\x2', '\x2', '\x2', '\xAF', '\xB0', '\a', '\x16', '\x2', '\x2', '\xB0', + '\xB1', '\x5', 'H', '%', '\x2', '\xB1', '\x1D', '\x3', '\x2', '\x2', '\x2', + '\xB2', '\xB5', '\a', '\x44', '\x2', '\x2', '\xB3', '\xB6', '\x5', '\x1E', + '\x10', '\x2', '\xB4', '\xB6', '\x5', '\x1A', '\xE', '\x2', '\xB5', '\xB3', + '\x3', '\x2', '\x2', '\x2', '\xB5', '\xB4', '\x3', '\x2', '\x2', '\x2', + '\xB6', '\xB7', '\x3', '\x2', '\x2', '\x2', '\xB7', '\xB8', '\a', '\x45', + '\x2', '\x2', '\xB8', '\x1F', '\x3', '\x2', '\x2', '\x2', '\xB9', '\xBA', + '\a', '\x17', '\x2', '\x2', '\xBA', '\xBD', '\x5', '\x46', '$', '\x2', + '\xBB', '\xBC', '\a', '\x1D', '\x2', '\x2', '\xBC', '\xBE', '\x5', 'H', + '%', '\x2', '\xBD', '\xBB', '\x3', '\x2', '\x2', '\x2', '\xBD', '\xBE', + '\x3', '\x2', '\x2', '\x2', '\xBE', '!', '\x3', '\x2', '\x2', '\x2', '\xBF', + '\xC0', '\t', '\x3', '\x2', '\x2', '\xC0', '\xC1', '\x5', 'H', '%', '\x2', + '\xC1', '#', '\x3', '\x2', '\x2', '\x2', '\xC2', '\xC3', '\t', '\x4', + '\x2', '\x2', '\xC3', '\xC4', '\x5', '&', '\x14', '\x2', '\xC4', '%', + '\x3', '\x2', '\x2', '\x2', '\xC5', '\xC7', '\a', '\x44', '\x2', '\x2', + '\xC6', '\xC8', '\x5', '(', '\x15', '\x2', '\xC7', '\xC6', '\x3', '\x2', + '\x2', '\x2', '\xC7', '\xC8', '\x3', '\x2', '\x2', '\x2', '\xC8', '\xC9', + '\x3', '\x2', '\x2', '\x2', '\xC9', '\xCA', '\a', '\x45', '\x2', '\x2', + '\xCA', '\'', '\x3', '\x2', '\x2', '\x2', '\xCB', '\xD0', '\x5', 'T', + '+', '\x2', '\xCC', '\xCD', '\a', '\x41', '\x2', '\x2', '\xCD', '\xCF', + '\x5', 'T', '+', '\x2', '\xCE', '\xCC', '\x3', '\x2', '\x2', '\x2', '\xCF', + '\xD2', '\x3', '\x2', '\x2', '\x2', '\xD0', '\xCE', '\x3', '\x2', '\x2', + '\x2', '\xD0', '\xD1', '\x3', '\x2', '\x2', '\x2', '\xD1', ')', '\x3', + '\x2', '\x2', '\x2', '\xD2', '\xD0', '\x3', '\x2', '\x2', '\x2', '\xD3', + '\xD4', '\a', '\'', '\x2', '\x2', '\xD4', '\xD5', '\x5', 'T', '+', '\x2', + '\xD5', '+', '\x3', '\x2', '\x2', '\x2', '\xD6', '\xDB', '\x5', '.', '\x18', + '\x2', '\xD7', '\xD8', '\a', '\x41', '\x2', '\x2', '\xD8', '\xDA', '\x5', + '.', '\x18', '\x2', '\xD9', '\xD7', '\x3', '\x2', '\x2', '\x2', '\xDA', + '\xDD', '\x3', '\x2', '\x2', '\x2', '\xDB', '\xD9', '\x3', '\x2', '\x2', + '\x2', '\xDB', '\xDC', '\x3', '\x2', '\x2', '\x2', '\xDC', '-', '\x3', + '\x2', '\x2', '\x2', '\xDD', '\xDB', '\x3', '\x2', '\x2', '\x2', '\xDE', + '\xE1', '\x5', '\x32', '\x1A', '\x2', '\xDF', '\xE1', '\x5', '\x30', '\x19', + '\x2', '\xE0', '\xDE', '\x3', '\x2', '\x2', '\x2', '\xE0', '\xDF', '\x3', + '\x2', '\x2', '\x2', '\xE1', '/', '\x3', '\x2', '\x2', '\x2', '\xE2', + '\xE3', '\a', ' ', '\x2', '\x2', '\xE3', '\xE4', '\a', '\x1B', '\x2', + '\x2', '\xE4', '\xE5', '\x3', '\x2', '\x2', '\x2', '\xE5', '\xE6', '\x5', + '>', ' ', '\x2', '\xE6', '\x31', '\x3', '\x2', '\x2', '\x2', '\xE7', '\xE8', + '\x5', '\x42', '\"', '\x2', '\xE8', '\xE9', '\x5', '\x34', '\x1B', '\x2', + '\xE9', '\x33', '\x3', '\x2', '\x2', '\x2', '\xEA', '\xEE', '\x5', '\x36', + '\x1C', '\x2', '\xEB', '\xED', '\x5', ':', '\x1E', '\x2', '\xEC', '\xEB', + '\x3', '\x2', '\x2', '\x2', '\xED', '\xF0', '\x3', '\x2', '\x2', '\x2', + '\xEE', '\xEC', '\x3', '\x2', '\x2', '\x2', '\xEE', '\xEF', '\x3', '\x2', + '\x2', '\x2', '\xEF', '\x35', '\x3', '\x2', '\x2', '\x2', '\xF0', '\xEE', + '\x3', '\x2', '\x2', '\x2', '\xF1', '\xF8', '\a', '\x1A', '\x2', '\x2', + '\xF2', '\xF8', '\a', '\x15', '\x2', '\x2', '\xF3', '\xF5', '\a', '\x10', + '\x2', '\x2', '\xF4', '\xF6', '\x5', '\x38', '\x1D', '\x2', '\xF5', '\xF4', + '\x3', '\x2', '\x2', '\x2', '\xF5', '\xF6', '\x3', '\x2', '\x2', '\x2', + '\xF6', '\xF8', '\x3', '\x2', '\x2', '\x2', '\xF7', '\xF1', '\x3', '\x2', + '\x2', '\x2', '\xF7', '\xF2', '\x3', '\x2', '\x2', '\x2', '\xF7', '\xF3', + '\x3', '\x2', '\x2', '\x2', '\xF8', '\x37', '\x3', '\x2', '\x2', '\x2', + '\xF9', '\xFA', '\a', '\x44', '\x2', '\x2', '\xFA', '\xFB', '\a', '\x5', + '\x2', '\x2', '\xFB', '\xFC', '\a', '\x45', '\x2', '\x2', '\xFC', '\x39', + '\x3', '\x2', '\x2', '\x2', '\xFD', '\xFF', '\a', '$', '\x2', '\x2', '\xFE', + '\x100', '\a', '\x1B', '\x2', '\x2', '\xFF', '\xFE', '\x3', '\x2', '\x2', + '\x2', '\xFF', '\x100', '\x3', '\x2', '\x2', '\x2', '\x100', ';', '\x3', + '\x2', '\x2', '\x2', '\x101', '\x102', '\a', '\x1D', '\x2', '\x2', '\x102', + '\x103', '\x5', 'H', '%', '\x2', '\x103', '\x104', '\x5', '>', ' ', '\x2', + '\x104', '=', '\x3', '\x2', '\x2', '\x2', '\x105', '\x106', '\a', '\x44', + '\x2', '\x2', '\x106', '\x107', '\x5', '\x44', '#', '\x2', '\x107', '\x108', + '\a', '\x45', '\x2', '\x2', '\x108', '?', '\x3', '\x2', '\x2', '\x2', + '\x109', '\x10A', '\x5', 'R', '*', '\x2', '\x10A', '\x41', '\x3', '\x2', + '\x2', '\x2', '\x10B', '\x10C', '\x5', 'J', '&', '\x2', '\x10C', '\x43', + '\x3', '\x2', '\x2', '\x2', '\x10D', '\x10E', '\x5', 'P', ')', '\x2', + '\x10E', '\x45', '\x3', '\x2', '\x2', '\x2', '\x10F', '\x110', '\x5', + 'J', '&', '\x2', '\x110', 'G', '\x3', '\x2', '\x2', '\x2', '\x111', '\x112', + '\x5', 'R', '*', '\x2', '\x112', 'I', '\x3', '\x2', '\x2', '\x2', '\x113', + '\x114', '\x5', 'R', '*', '\x2', '\x114', 'K', '\x3', '\x2', '\x2', '\x2', + '\x115', '\x116', '\x5', 'P', ')', '\x2', '\x116', 'M', '\x3', '\x2', + '\x2', '\x2', '\x117', '\x118', '\a', 'J', '\x2', '\x2', '\x118', 'O', + '\x3', '\x2', '\x2', '\x2', '\x119', '\x11A', '\x5', 'N', '(', '\x2', + '\x11A', 'Q', '\x3', '\x2', '\x2', '\x2', '\x11B', '\x11C', '\x5', 'P', + ')', '\x2', '\x11C', 'S', '\x3', '\x2', '\x2', '\x2', '\x11D', '\x11E', + '\b', '+', '\x1', '\x2', '\x11E', '\x11F', '\a', '\x44', '\x2', '\x2', + '\x11F', '\x120', '\x5', 'T', '+', '\x2', '\x120', '\x121', '\a', '\x45', + '\x2', '\x2', '\x121', '\x128', '\x3', '\x2', '\x2', '\x2', '\x122', '\x123', + '\t', '\x5', '\x2', '\x2', '\x123', '\x128', '\x5', 'T', '+', '\v', '\x124', + '\x125', '\a', '\x1C', '\x2', '\x2', '\x125', '\x128', '\x5', 'T', '+', + '\n', '\x126', '\x128', '\x5', 'X', '-', '\x2', '\x127', '\x11D', '\x3', + '\x2', '\x2', '\x2', '\x127', '\x122', '\x3', '\x2', '\x2', '\x2', '\x127', + '\x124', '\x3', '\x2', '\x2', '\x2', '\x127', '\x126', '\x3', '\x2', '\x2', + '\x2', '\x128', '\x13E', '\x3', '\x2', '\x2', '\x2', '\x129', '\x12A', + '\f', '\t', '\x2', '\x2', '\x12A', '\x12B', '\t', '\x6', '\x2', '\x2', + '\x12B', '\x13D', '\x5', 'T', '+', '\n', '\x12C', '\x12D', '\f', '\b', + '\x2', '\x2', '\x12D', '\x12E', '\t', '\x5', '\x2', '\x2', '\x12E', '\x13D', + '\x5', 'T', '+', '\t', '\x12F', '\x130', '\f', '\a', '\x2', '\x2', '\x130', + '\x131', '\x5', 'V', ',', '\x2', '\x131', '\x132', '\x5', 'T', '+', '\b', + '\x132', '\x13D', '\x3', '\x2', '\x2', '\x2', '\x133', '\x134', '\f', + '\x6', '\x2', '\x2', '\x134', '\x135', '\t', '\a', '\x2', '\x2', '\x135', + '\x13D', '\x5', 'T', '+', '\a', '\x136', '\x137', '\f', '\x5', '\x2', + '\x2', '\x137', '\x138', '\a', ')', '\x2', '\x2', '\x138', '\x13D', '\x5', + 'T', '+', '\x6', '\x139', '\x13A', '\f', '\x4', '\x2', '\x2', '\x13A', + '\x13B', '\t', '\b', '\x2', '\x2', '\x13B', '\x13D', '\x5', 'T', '+', + '\x5', '\x13C', '\x129', '\x3', '\x2', '\x2', '\x2', '\x13C', '\x12C', + '\x3', '\x2', '\x2', '\x2', '\x13C', '\x12F', '\x3', '\x2', '\x2', '\x2', + '\x13C', '\x133', '\x3', '\x2', '\x2', '\x2', '\x13C', '\x136', '\x3', + '\x2', '\x2', '\x2', '\x13C', '\x139', '\x3', '\x2', '\x2', '\x2', '\x13D', + '\x140', '\x3', '\x2', '\x2', '\x2', '\x13E', '\x13C', '\x3', '\x2', '\x2', + '\x2', '\x13E', '\x13F', '\x3', '\x2', '\x2', '\x2', '\x13F', 'U', '\x3', + '\x2', '\x2', '\x2', '\x140', '\x13E', '\x3', '\x2', '\x2', '\x2', '\x141', + '\x142', '\t', '\t', '\x2', '\x2', '\x142', 'W', '\x3', '\x2', '\x2', + '\x2', '\x143', '\x146', '\x5', 'Z', '.', '\x2', '\x144', '\x146', '\x5', + '\\', '/', '\x2', '\x145', '\x143', '\x3', '\x2', '\x2', '\x2', '\x145', + '\x144', '\x3', '\x2', '\x2', '\x2', '\x146', 'Y', '\x3', '\x2', '\x2', + '\x2', '\x147', '\x148', '\t', '\n', '\x2', '\x2', '\x148', '[', '\x3', + '\x2', '\x2', '\x2', '\x149', '\x14A', '\x5', 'P', ')', '\x2', '\x14A', + ']', '\x3', '\x2', '\x2', '\x2', '\x1C', '\x64', 'h', 's', '\x80', '\x88', + '\x8B', '\x94', '\x9A', '\x9E', '\xA5', '\xAA', '\xAD', '\xB5', '\xBD', + '\xC7', '\xD0', '\xDB', '\xE0', '\xEE', '\xF5', '\xF7', '\xFF', '\x127', + '\x13C', '\x13E', '\x145', }; public static readonly ATN _ATN = diff --git a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLVisitor.cs b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLVisitor.cs index daba4a3..60e35eb 100644 --- a/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLVisitor.cs +++ b/src/MiniSQL.Interpreter/Grammar/MiniSQL/MiniSQLVisitor.cs @@ -56,6 +56,12 @@ public interface IMiniSQLVisitor : IParseTreeVisitor { /// The visitor result. Result VisitExecFileStatement([NotNull] MiniSQLParser.ExecFileStatementContext context); /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context); + /// /// Visit a parse tree produced by . /// /// The parse tree. diff --git a/src/MiniSQL.Interpreter/Grammar/README.md b/src/MiniSQL.Interpreter/Grammar/README.md index 47bb96b..044bf0d 100644 --- a/src/MiniSQL.Interpreter/Grammar/README.md +++ b/src/MiniSQL.Interpreter/Grammar/README.md @@ -25,6 +25,10 @@ REM grun.cmd java -cp .;"PATH\TO\antlr-4.8-complete.jar" org.antlr.v4.gui.TestRig %* ``` +```powershell +dotnet add package Antlr4.Runtime.Standard +``` + ## Generate code Set `pwd` to current folder first. Then run the following command. @@ -39,6 +43,7 @@ antlr -Dlanguage=CSharp -visitor -o MiniSQL MiniSQL.g4 1. inherit it from IYOURGRAMMARNAMEVisiter 1. resolve errors 1. inherit it from YOURGRAMMARNAMEBaseVisiter +1. add keyword `override` to all methods 1. delete unnecessary methods 1. implement remaining methods diff --git a/src/MiniSQL.Interpreter/Grammar/tests/table-insert-delete-1.sql b/src/MiniSQL.Interpreter/Grammar/tests/table-insert-delete-1.sql index aafbf9e..eedf10c 100644 --- a/src/MiniSQL.Interpreter/Grammar/tests/table-insert-delete-1.sql +++ b/src/MiniSQL.Interpreter/Grammar/tests/table-insert-delete-1.sql @@ -36,4 +36,5 @@ delete from person where age <= 20 and height < 170 and name = "Person16"; select * from person; -drop table persion; +-- drop table persion; +drop table person; diff --git a/src/MiniSQL.Interpreter/MiniSQL.Interpreter.csproj b/src/MiniSQL.Interpreter/MiniSQL.Interpreter.csproj index 93663e4..c454fd7 100644 --- a/src/MiniSQL.Interpreter/MiniSQL.Interpreter.csproj +++ b/src/MiniSQL.Interpreter/MiniSQL.Interpreter.csproj @@ -5,12 +5,12 @@ - + - Exe - netcoreapp3.1 + + net5.0 diff --git a/src/MiniSQL.Interpreter/Program.cs b/src/MiniSQL.Interpreter/Program.cs index fb6f84b..55c74f4 100644 --- a/src/MiniSQL.Interpreter/Program.cs +++ b/src/MiniSQL.Interpreter/Program.cs @@ -2,6 +2,7 @@ using System.IO; using Antlr4.Runtime; using Antlr4.Runtime.Tree; +using MiniSQL.Interpreter.Controllers; namespace MiniSQL.Interpreter { diff --git a/src/MiniSQL.Interpreter/Visitor/MiniSQLVisitor.cs b/src/MiniSQL.Interpreter/Visitor/MiniSQLVisitor.cs index 28ffba1..fef9097 100644 --- a/src/MiniSQL.Interpreter/Visitor/MiniSQLVisitor.cs +++ b/src/MiniSQL.Interpreter/Visitor/MiniSQLVisitor.cs @@ -176,8 +176,8 @@ public override object VisitExprAdd([NotNull] MiniSQLParser.ExprAddContext conte Expression left = (Expression)Visit(context.expr(0)); Expression right = (Expression)Visit(context.expr(1)); Expression obj = new Expression(); - obj.LeftOperant = left; - obj.RightOperant = right; + obj.LeftOperand = left; + obj.RightOperand = right; if (context.PLUS_OPERATOR() != null) obj.Operator = Operator.Plus; else @@ -197,8 +197,8 @@ public override object VisitExprAnd([NotNull] MiniSQLParser.ExprAndContext conte Expression left = (Expression)Visit(context.expr(0)); Expression right = (Expression)Visit(context.expr(1)); Expression obj = new Expression(); - obj.LeftOperant = left; - obj.RightOperant = right; + obj.LeftOperand = left; + obj.RightOperand = right; obj.Operator = Operator.And; // optimize expression if (left.Operator == Operator.AtomConcreteValue @@ -220,8 +220,8 @@ public override object VisitExprCompare([NotNull] MiniSQLParser.ExprCompareConte Expression left = (Expression)Visit(context.expr(0)); Expression right = (Expression)Visit(context.expr(1)); Expression obj = new Expression(); - obj.LeftOperant = left; - obj.RightOperant = right; + obj.LeftOperand = left; + obj.RightOperand = right; if (context.compOp().EQUAL_OPERATOR() != null) obj.Operator = Operator.Equal; else if (context.compOp().GREATER_OR_EQUAL_OPERATOR() != null) @@ -251,8 +251,8 @@ public override object VisitExprMul([NotNull] MiniSQLParser.ExprMulContext conte Expression left = (Expression)Visit(context.expr(0)); Expression right = (Expression)Visit(context.expr(1)); Expression obj = new Expression(); - obj.LeftOperant = left; - obj.RightOperant = right; + obj.LeftOperand = left; + obj.RightOperand = right; if (context.MULT_OPERATOR() != null) obj.Operator = Operator.Multiply; else @@ -286,7 +286,7 @@ public override object VisitExprNot([NotNull] MiniSQLParser.ExprNotContext conte // return left; // } Expression obj = new Expression(); - obj.LeftOperant = left; + obj.LeftOperand = left; obj.Operator = Operator.Not; // optimize expression if (left.Operator == Operator.AtomConcreteValue) @@ -302,8 +302,8 @@ public override object VisitExprOr([NotNull] MiniSQLParser.ExprOrContext context Expression left = (Expression)Visit(context.expr(0)); Expression right = (Expression)Visit(context.expr(1)); Expression obj = new Expression(); - obj.LeftOperant = left; - obj.RightOperant = right; + obj.LeftOperand = left; + obj.RightOperand = right; obj.Operator = Operator.Or; // optimize expression if (left.Operator == Operator.AtomConcreteValue @@ -341,7 +341,7 @@ public override object VisitExprSign([NotNull] MiniSQLParser.ExprSignContext con // return left; // } Expression obj = new Expression(); - obj.LeftOperant = left; + obj.LeftOperand = left; obj.Operator = Operator.Negative; // optimize expression if (left.Operator == Operator.AtomConcreteValue) @@ -357,8 +357,8 @@ public override object VisitExprXor([NotNull] MiniSQLParser.ExprXorContext conte Expression left = (Expression)Visit(context.expr(0)); Expression right = (Expression)Visit(context.expr(1)); Expression obj = new Expression(); - obj.LeftOperant = left; - obj.RightOperant = right; + obj.LeftOperand = left; + obj.RightOperand = right; obj.Operator = Operator.Xor; // optimize expression if (left.Operator == Operator.AtomConcreteValue @@ -520,6 +520,13 @@ public override object VisitSelectStatement([NotNull] MiniSQLParser.SelectStatem return (SelectStatement)Visit(context.queryExpressionParens()); } + public override object VisitShowTablesStatement([NotNull] MiniSQLParser.ShowTablesStatementContext context) + { + ShowStatement statement = new ShowStatement(); + statement.ShowType = ShowType.Table; + return statement; + } + public override object VisitSimpleStatement([NotNull] MiniSQLParser.SimpleStatementContext context) { if (context.createStatement() != null) @@ -536,6 +543,8 @@ public override object VisitSimpleStatement([NotNull] MiniSQLParser.SimpleStatem return (IStatement)Visit(context.quitStatement()); else if (context.selectStatement() != null) return (IStatement)Visit(context.selectStatement()); + else if (context.showTablesStatement() != null) + return (IStatement)Visit(context.showTablesStatement()); else throw new System.NotImplementedException(); } 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 39e07cf..b1dcecf 100644 --- a/src/MiniSQL.Library/Interfaces/ICatalogManager.cs +++ b/src/MiniSQL.Library/Interfaces/ICatalogManager.cs @@ -1,35 +1,35 @@ +using System; using System.Collections.Generic; using MiniSQL.Library.Models; -using System; -using System.ComponentModel; -using System.IO; -using System.Runtime.InteropServices.ComTypes; -using System.Runtime.Serialization.Formatters.Binary; -using System.Text; -using System.Diagnostics; namespace MiniSQL.Library.Interfaces { - - // TODO: review + public interface ICatalogManager { // try to save the create statement into file as a few schema records // if succeeded, return true. Vice versa bool TryCreateStatement(CreateStatement createStatement, int rootPage); + // save the create statement into file as a few schema records + void CreateStatement(CreateStatement createStatement, int rootPage); // try to remove some schema records from file // if succeeded, return true. Vice versa bool TryDropStatement(DropStatement dropStatement); + // remove some schema records from file + void DropStatement(DropStatement dropStatement); // update the root page of a table or an index // if succeeded, return true. Vice versa bool TryUpdateSchemaRecord(string name, int rootPage); - // according to the table name required, return corresponding schema record + // according to the table name requested, return corresponding schema record SchemaRecord GetTableSchemaRecord(string tableName); - // according to the table name required, return the all index schema records that is associated to the table + // according to the table name requested, return the all index schema records that is associated to the table List GetIndicesSchemaRecord(string tableName); - // according to the index name required, return corresponding schema record + // return the all table schema records in this database file + List GetTablesSchemaRecord(); + // according to the index name requested, return corresponding schema record SchemaRecord GetIndexSchemaRecord(string indexName); // check validation of the statement bool IsValid(IStatement statement); + void CheckValidation(IStatement statement); } } diff --git a/src/MiniSQL.Library/Interfaces/IRecordManager.cs b/src/MiniSQL.Library/Interfaces/IRecordManager.cs index a0da0fb..2fd5b54 100644 --- a/src/MiniSQL.Library/Interfaces/IRecordManager.cs +++ b/src/MiniSQL.Library/Interfaces/IRecordManager.cs @@ -3,7 +3,6 @@ namespace MiniSQL.Library.Interfaces { - // TODO: review public interface IRecordManager { // return the root page number of the table tree diff --git a/src/MiniSQL.Library/MiniSQL.Library.csproj b/src/MiniSQL.Library/MiniSQL.Library.csproj index c73e0d1..9724adc 100644 --- a/src/MiniSQL.Library/MiniSQL.Library.csproj +++ b/src/MiniSQL.Library/MiniSQL.Library.csproj @@ -1,8 +1,8 @@ - Exe - netcoreapp3.1 + + net5.0 diff --git a/src/MiniSQL.Library/Models/Statement/Atom/AtomValue.cs b/src/MiniSQL.Library/Models/Statement/Atom/AtomValue.cs index 9fdfa06..7dfd49f 100644 --- a/src/MiniSQL.Library/Models/Statement/Atom/AtomValue.cs +++ b/src/MiniSQL.Library/Models/Statement/Atom/AtomValue.cs @@ -469,7 +469,7 @@ private static void ThrowErrorIfNotSameType(AtomValue leftValue, AtomValue right // make sure the types of children are the same if (leftValue?.Type != rightValue?.Type) { - throw new System.Exception("Operants type not matched!"); + throw new System.Exception("Operands type not matched!"); } } @@ -494,5 +494,17 @@ public override int GetHashCode() return 0; } } + + public override string ToString() + { + return this.Type switch + { + AttributeTypes.Null => "null", + AttributeTypes.Int => this.IntegerValue.ToString(), + AttributeTypes.Char => this.StringValue, + AttributeTypes.Float => this.FloatValue.ToString(), + _ => null, + }; + } } } diff --git a/src/MiniSQL.Library/Models/Statement/Expression.cs b/src/MiniSQL.Library/Models/Statement/Expression.cs index 01864ea..c08a78e 100644 --- a/src/MiniSQL.Library/Models/Statement/Expression.cs +++ b/src/MiniSQL.Library/Models/Statement/Expression.cs @@ -29,42 +29,43 @@ public enum Operator public class Expression { public Operator Operator { get; set; } - public Expression LeftOperant { get; set; } = null; - // if nary, this.RightOperant will be null - public Expression RightOperant { get; set; } = null; + public Expression LeftOperand { get; set; } = null; + // if nary, this.RightOperand will be null + public Expression RightOperand { get; set; } = null; // use if this Expression is only the attribute // this could be a number or a string public AtomValue ConcreteValue { get; set; } = null; // use if this Expression is only an attribute (variable) public string AttributeName { get; set; } = ""; - - // {attribute name: expression with only the variable/attribute} - private Dictionary ands = null; + private Dictionary simpleMinterms = null; // to help B-Tree's single key searching // NOTICE: never try to modify it by yourself - public Dictionary Ands + // only contains simple expressions, with left child being variable, right child being concrete value, and root being non-and operator. + // might include false negative + // tolerate false negative + public Dictionary SimpleMinterms { get { - if (this.ands == null) + if (this.simpleMinterms == null) { - this.ands = new Dictionary(); - this.BuildAndList(); - return this.ands; + this.simpleMinterms = new Dictionary(); + this.BuildSimpleMinterms(); + return this.simpleMinterms; } else - return this.ands; + return this.simpleMinterms; } } - private void BuildAndList() + private void BuildSimpleMinterms() { if (this.Operator == Operator.AtomConcreteValue || this.Operator == Operator.AtomVariable) { return; } - this.LeftOperant.BuildAndList(); - this.RightOperant.BuildAndList(); + this.LeftOperand.BuildSimpleMinterms(); + this.RightOperand.BuildSimpleMinterms(); if (this.Operator == Operator.Equal || this.Operator == Operator.LessThan @@ -75,13 +76,13 @@ private void BuildAndList() // || this.Operator == Operator.NotEqual ) { - if (this.LeftOperant.Operator == Operator.AtomConcreteValue - && this.RightOperant.Operator == Operator.AtomVariable) + if (this.LeftOperand.Operator == Operator.AtomConcreteValue + && this.RightOperand.Operator == Operator.AtomVariable) { // swap variable to the left - Expression tmp = this.LeftOperant; - this.LeftOperant = this.RightOperant; - this.RightOperant = tmp; + Expression tmp = this.LeftOperand; + this.LeftOperand = this.RightOperand; + this.RightOperand = tmp; // change operator switch (this.Operator) { @@ -99,32 +100,33 @@ private void BuildAndList() break; } // add to the "and" list - this.Ands[this.LeftOperant.AttributeName] = this; + this.SimpleMinterms[this.LeftOperand.AttributeName] = this; } - else if (this.LeftOperant.Operator == Operator.AtomVariable - && this.RightOperant.Operator == Operator.AtomConcreteValue) - this.Ands[this.LeftOperant.AttributeName] = this; + else if (this.LeftOperand.Operator == Operator.AtomVariable + && this.RightOperand.Operator == Operator.AtomConcreteValue) + this.SimpleMinterms[this.LeftOperand.AttributeName] = this; } - // only operator `and` could take `Ands` in its children + // only operator `and` could take `SimpleMinterms` in its children else if (this.Operator == Operator.And) { - foreach (var andExpresion in this.LeftOperant.Ands.ToList()) + foreach (var andExpresion in this.LeftOperand.SimpleMinterms.ToList()) { - this.Ands[andExpresion.Key] = andExpresion.Value; + this.SimpleMinterms[andExpresion.Key] = andExpresion.Value; } // duplicate key will be overwritten - foreach (var andExpresion in this.RightOperant.Ands.ToList()) + foreach (var andExpresion in this.RightOperand.SimpleMinterms.ToList()) { - this.Ands[andExpresion.Key] = andExpresion.Value; + this.SimpleMinterms[andExpresion.Key] = andExpresion.Value; } } } + // check if a value could satisfy part of the expression public bool CheckKey(string attributeName, AtomValue valueToCheck) { - if (this.Ands.ContainsKey(attributeName)) + if (this.SimpleMinterms.ContainsKey(attributeName)) { - AtomValue result = this.Ands[attributeName].Calculate(new List + AtomValue result = this.SimpleMinterms[attributeName].Calculate(new List { new AttributeValue(attributeName, new AtomValue() { @@ -165,14 +167,14 @@ public AtomValue Calculate(List row) return this.ConcreteValue; // fetch the values of children - AtomValue leftValue = this.LeftOperant?.Calculate(row); - AtomValue rightValue = this.RightOperant?.Calculate(row); + AtomValue leftValue = this.LeftOperand?.Calculate(row); + AtomValue rightValue = this.RightOperand?.Calculate(row); AtomValue result = null; // // make sure the types of children are the same // if (leftValue?.Type != rightValue?.Type) // { - // throw new System.Exception("Operands type not matched!"); + // throw new System.Exception("OpersimpleMinterms type not matched!"); // } // calculate the two children into a value diff --git a/src/MiniSQL.Library/Models/Statement/Statements/IStatement.cs b/src/MiniSQL.Library/Models/Statement/Statements/IStatement.cs index 5536ee9..02114da 100644 --- a/src/MiniSQL.Library/Models/Statement/Statements/IStatement.cs +++ b/src/MiniSQL.Library/Models/Statement/Statements/IStatement.cs @@ -14,6 +14,7 @@ public enum StatementType // Custom QuitStatement, ExecFileStatement, + ShowStatement, } public interface IStatement diff --git a/src/MiniSQL.Library/Models/Statement/Statements/ShowStatement.cs b/src/MiniSQL.Library/Models/Statement/Statements/ShowStatement.cs new file mode 100644 index 0000000..8e331ed --- /dev/null +++ b/src/MiniSQL.Library/Models/Statement/Statements/ShowStatement.cs @@ -0,0 +1,16 @@ +namespace MiniSQL.Library.Models +{ + public enum ShowType + { + Table, + Index, + Database + } + + public class ShowStatement : IStatement + { + public StatementType Type { get; set; } = StatementType.ShowStatement; + public ShowType ShowType { get; set; } + public string FromTable { get; set; } + } +} diff --git a/src/MiniSQL.Library/Program.cs b/src/MiniSQL.Library/Program.cs index cf8238b..1edaf3a 100644 --- a/src/MiniSQL.Library/Program.cs +++ b/src/MiniSQL.Library/Program.cs @@ -105,22 +105,24 @@ private static void TestCalculateSingleValue() private static void TestAndList() { Expression andsExpression = GetAndsExpression(); - var andList = andsExpression.Ands; + var andList = andsExpression.SimpleMinterms; // "not equal" operator is ignored Debug.Assert(andList.ContainsKey("a") == false); Debug.Assert(andList["b"].Operator == Operator.LessThanOrEqualTo); - Debug.Assert(andList["b"].RightOperant.ConcreteValue.StringValue == "str"); + Debug.Assert(andList["b"].RightOperand.ConcreteValue.StringValue == "str"); Debug.Assert(andList["c"].Operator == Operator.LessThan); - Debug.Assert(andList["c"].RightOperant.ConcreteValue.FloatValue == 6.6); + Debug.Assert(andList["c"].RightOperand.ConcreteValue.FloatValue == 6.6); } private static Expression GetAndsExpression() { + // __expression__ + // ((32 != a) and (b <= "str")) and (6.6> c) // __tree structure__ - // and 1 - // and 2,> 3 - // != 4, <= 5, 6.6 6, c 7 - // 32 8, a, 9, b 10, "str" 11 + // and 1 + // and 2,> 3 + // != 4, <= 5, 6.6 6, c 7 + // 32 8, a 9, b 10, "str" 11 // 32 Expression node8 = new Expression(); @@ -146,13 +148,13 @@ private static Expression GetAndsExpression() // != Expression node4 = new Expression(); node4.Operator = Operator.NotEqual; - node4.LeftOperant = node8; - node4.RightOperant = node9; + node4.LeftOperand = node8; + node4.RightOperand = node9; // <= Expression node5 = new Expression(); node5.Operator = Operator.LessThanOrEqualTo; - node5.LeftOperant = node10; - node5.RightOperant = node11; + node5.LeftOperand = node10; + node5.RightOperand = node11; // 6.6 Expression node6 = new Expression(); node6.Operator = Operator.AtomConcreteValue; @@ -166,18 +168,18 @@ private static Expression GetAndsExpression() // and Expression node2 = new Expression(); node2.Operator = Operator.And; - node2.LeftOperant = node4; - node2.RightOperant = node5; + node2.LeftOperand = node4; + node2.RightOperand = node5; //> Expression node3 = new Expression(); node3.Operator = Operator.MoreThan; - node3.LeftOperant = node6; - node3.RightOperant = node7; + node3.LeftOperand = node6; + node3.RightOperand = node7; // and Expression node1 = new Expression(); node1.Operator = Operator.And; - node1.LeftOperant = node2; - node1.RightOperant = node3; + node1.LeftOperand = node2; + node1.RightOperand = node3; return node1; } diff --git a/src/MiniSQL.RecordManager/RecordContext.cs b/src/MiniSQL.RecordManager/Controllers/RecordContext.cs similarity index 94% rename from src/MiniSQL.RecordManager/RecordContext.cs rename to src/MiniSQL.RecordManager/Controllers/RecordContext.cs index a4ad69a..c7b4048 100644 --- a/src/MiniSQL.RecordManager/RecordContext.cs +++ b/src/MiniSQL.RecordManager/Controllers/RecordContext.cs @@ -7,7 +7,7 @@ using MiniSQL.Library.Interfaces; using MiniSQL.Library.Models; -namespace MiniSQL.RecordManager +namespace MiniSQL.RecordManager.Controllers { // TODO: review + test public class RecordContext : IRecordManager @@ -23,7 +23,7 @@ public RecordContext(Pager pager, IIndexManager bTreeController) public int CreateTable() { - return _bTree.OccupyNewTableNode().GetRawPage().PageNumber; + return _bTree.OccupyNewTableNode().RawPage.PageNumber; } public int CreateIndex(int tableRootPage, string indexedColumnName, List attributeDeclarations) @@ -45,14 +45,14 @@ public int CreateIndex(int tableRootPage, string indexedColumnName, List attributeDeclarations, int rootPage) { BTreeNode node = BTreeNodeHelper.GetBTreeNode(_pager, rootPage); BTreeNode newRoot = _bTree.DeleteCells(node, condition, primaryKeyName, attributeDeclarations); - return newRoot.GetRawPage().PageNumber; + return newRoot.RawPage.PageNumber; } public int DeleteRecords(List primaryKeys, int rootPage) @@ -74,7 +74,7 @@ public int InsertRecord(List values, AtomValue key, int rootPage) DBRecord wrappedKey = new DBRecord(new List() { key }); DBRecord wrappedValues = new DBRecord(values); BTreeNode newRoot = _bTree.InsertCell(node, wrappedKey, wrappedValues); - return newRoot.GetRawPage().PageNumber; + return newRoot.RawPage.PageNumber; } public List> SelectRecords(SelectStatement selectStatement, string primaryKeyName, List attributeDeclarations, int rootPage) diff --git a/src/MiniSQL.RecordManager/MiniSQL.RecordManager.csproj b/src/MiniSQL.RecordManager/MiniSQL.RecordManager.csproj index 7096ce8..40a2f9a 100644 --- a/src/MiniSQL.RecordManager/MiniSQL.RecordManager.csproj +++ b/src/MiniSQL.RecordManager/MiniSQL.RecordManager.csproj @@ -7,8 +7,8 @@ - Exe - netcoreapp3.1 + + net5.0 diff --git a/src/MiniSQL.RecordManager/Program.cs b/src/MiniSQL.RecordManager/Program.cs index 34d0170..e7c40e4 100644 --- a/src/MiniSQL.RecordManager/Program.cs +++ b/src/MiniSQL.RecordManager/Program.cs @@ -3,11 +3,11 @@ using System.Diagnostics; using System.IO; using MiniSQL.BufferManager.Controllers; -using MiniSQL.BufferManager.Models; using MiniSQL.IndexManager.Controllers; using MiniSQL.IndexManager.Models; using MiniSQL.IndexManager.Utilities; using MiniSQL.Library.Models; +using MiniSQL.RecordManager.Controllers; namespace MiniSQL.RecordManager { diff --git a/tests/MiniSQL.Api.Tests/MiniSQL.Api.Tests.csproj b/tests/MiniSQL.Api.Tests/MiniSQL.Api.Tests.csproj new file mode 100644 index 0000000..8573205 --- /dev/null +++ b/tests/MiniSQL.Api.Tests/MiniSQL.Api.Tests.csproj @@ -0,0 +1,27 @@ + + + + net5.0 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/tests/MiniSQL.Api.Tests/UnitTest1.cs b/tests/MiniSQL.Api.Tests/UnitTest1.cs new file mode 100644 index 0000000..cdc9267 --- /dev/null +++ b/tests/MiniSQL.Api.Tests/UnitTest1.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using MiniSQL.Api.Controllers; +using MiniSQL.Library.Interfaces; +using Xunit; + +namespace MiniSQL.Api.Tests +{ + public class UnitTest1 + { + [Fact] + public void SelectFromIndexTree() + { + DatabaseBuilder builder = new DatabaseBuilder(); + IApi databaseController = new ApiController(builder); + databaseController.DropDatabase("SelectFromIndexTree"); + databaseController.ChangeContext("SelectFromIndexTree"); + try + { + databaseController.Query( + @"create table student ( + sno char(8), + sname char(16) unique, + sage int, + sgender char(1), + primary key(sno) + );" + ); + databaseController.Query( + "create index stu_name_idx on student(sname);" + ); + databaseController.Query( + "insert into student values('1', 'st1', 21, 'M');" + ); + databaseController.Query( + "insert into student values('2', 'st2', 22, 'M');" + ); + databaseController.Query( + "insert into student values('3', 'st3', 23, 'M');" + ); + databaseController.Query( + "insert into student values('4', 'st4', 24, 'M');" + ); + List results = databaseController.Query( + "select * from student where sgender = 'M' and sage <= 24 and sage> 21 and sname = 'st3' and sno = '3';" + ); + Assert.Single(results); + Assert.Equal(4, results[0].ColumnDeclarations.Count); + Assert.Single(results[0].Rows); + Assert.Equal("3", results[0].Rows[0][0].StringValue); + Assert.Equal("st3", results[0].Rows[0][1].StringValue); + Assert.Equal(23, results[0].Rows[0][2].IntegerValue); + Assert.Equal("M", results[0].Rows[0][3].StringValue); + } + finally + { + databaseController.DropDatabase("SelectFromIndexTree"); + } + } + } +} diff --git a/tests/MiniSQL.BufferManager.Tests/MiniSQL.BufferManager.Tests.csproj b/tests/MiniSQL.BufferManager.Tests/MiniSQL.BufferManager.Tests.csproj new file mode 100644 index 0000000..3237240 --- /dev/null +++ b/tests/MiniSQL.BufferManager.Tests/MiniSQL.BufferManager.Tests.csproj @@ -0,0 +1,22 @@ + + + + net5.0 + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/tests/MiniSQL.BufferManager.Tests/UnitTest1.cs b/tests/MiniSQL.BufferManager.Tests/UnitTest1.cs new file mode 100644 index 0000000..10210ed --- /dev/null +++ b/tests/MiniSQL.BufferManager.Tests/UnitTest1.cs @@ -0,0 +1,250 @@ +using System; +using Xunit; +using System.Collections.Generic; +using System.IO; +using MiniSQL.BufferManager.Controllers; +using MiniSQL.BufferManager.Models; +using MiniSQL.Library.Models; + +namespace MiniSQL.BufferManager.Tests +{ + public class UnitTest1 + { + [Fact] + static void TestFreeList() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 100); + + List pageList = new List(); + pageList.Add(pager.GetNewPage()); // page #2 + pageList.Add(pager.GetNewPage()); // page #3 + pageList.Add(pager.GetNewPage()); // page #4 + pageList.Add(pager.GetNewPage()); // page #5 + + FreeList freeList = new FreeList(pager); + + // test initialization + MemoryPage newPage = null; + newPage = freeList.AllocatePage(); // freeList is now empty + Assert.Equal(newPage, null); + + // recycle pages + // MemoryPage tempPage = pager.ReadPage(3); + freeList.RecyclePage(pageList[2]); // freeList->4 + freeList.RecyclePage(pageList[1]); // freeList->3->4 + freeList.RecyclePage(pageList[3]); // freeList->5->3->4 + + // fetch page from free list + newPage = freeList.AllocatePage(); // freeList->3->4 + Assert.Equal(newPage.PageNumber, 5); + newPage = freeList.AllocatePage(); // freeList->4 + Assert.Equal(newPage.PageNumber, 3); + + // recycle a page + freeList.RecyclePage(pageList[3]); // freeList->5->4 + + // fetch remaining pages + newPage = freeList.AllocatePage(); // freeList->4 + Assert.Equal(newPage.PageNumber, 5); + newPage = freeList.AllocatePage(); // freeList->null + Assert.Equal(newPage.PageNumber, 4); + newPage = freeList.AllocatePage(); // freeList->null + Assert.Equal(newPage, null); + + pager.Close(); + } + + private static Expression GetAndsExpression() + { + // __tree structure__ + // and 1 + // and 2,> 3 + // <= 4, <= 5, 6.6 6, c 7 + // 15 8, a, 9, b 10, "str" 11 + + // 32 + Expression node8 = new Expression(); + node8.Operator = Operator.AtomConcreteValue; + node8.ConcreteValue = new AtomValue(); + node8.ConcreteValue.Type = AttributeTypes.Int; + node8.ConcreteValue.IntegerValue = 15; + // a + Expression node9 = new Expression(); + node9.Operator = Operator.AtomVariable; + node9.AttributeName = "a"; + // b + Expression node10 = new Expression(); + node10.Operator = Operator.AtomVariable; + node10.AttributeName = "b"; + // "str" + Expression node11 = new Expression(); + node11.Operator = Operator.AtomConcreteValue; + node11.ConcreteValue = new AtomValue(); + node11.ConcreteValue.Type = AttributeTypes.Char; + node11.ConcreteValue.CharLimit = 5; + node11.ConcreteValue.StringValue = "str"; + // <= + Expression node4 = new Expression(); + node4.Operator = Operator.LessThanOrEqualTo; + node4.LeftOperand = node8; + node4.RightOperand = node9; + // <= + Expression node5 = new Expression(); + node5.Operator = Operator.LessThanOrEqualTo; + node5.LeftOperand = node10; + node5.RightOperand = node11; + // 6.6 + Expression node6 = new Expression(); + node6.Operator = Operator.AtomConcreteValue; + node6.ConcreteValue = new AtomValue(); + node6.ConcreteValue.Type = AttributeTypes.Float; + node6.ConcreteValue.FloatValue = 6.6; + // c + Expression node7 = new Expression(); + node7.Operator = Operator.AtomVariable; + node7.AttributeName = "c"; + // and + Expression node2 = new Expression(); + node2.Operator = Operator.And; + node2.LeftOperand = node4; + node2.RightOperand = node5; + //> + Expression node3 = new Expression(); + node3.Operator = Operator.MoreThan; + node3.LeftOperand = node6; + node3.RightOperand = node7; + // and + Expression node1 = new Expression(); + node1.Operator = Operator.And; + node1.LeftOperand = node2; + node1.RightOperand = node3; + + return node1; + } + + [Fact] + static void TestPagerSwapping() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 4); + + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + // pager.ExtendNumberOfPages(); + + MemoryPage page1 = pager.ReadPage(1); + page1.IsPinned = true; + MemoryPage page2 = pager.ReadPage(2); + page2.Data[0] = 2; + MemoryPage page3 = pager.ReadPage(3); + MemoryPage page4 = pager.ReadPage(4); + MemoryPage page5 = pager.ReadPage(5); + Assert.Equal(page1.IsSwappedOut, false); + Assert.Equal(page2.IsSwappedOut, true); + Assert.Equal(page3.IsSwappedOut, false); + Assert.Equal(page4.IsSwappedOut, false); + Assert.Equal(page5.IsSwappedOut, false); + MemoryPage page6 = pager.ReadPage(6); + Assert.Equal(page1.IsSwappedOut, false); + Assert.Equal(page2.IsSwappedOut, true); + Assert.Equal(page3.IsSwappedOut, true); + Assert.Equal(page4.IsSwappedOut, false); + Assert.Equal(page5.IsSwappedOut, false); + Assert.Equal(page6.IsSwappedOut, false); + page4.Data[0] = 4; + page4[1] = 44; + MemoryPage page7 = pager.ReadPage(7); + Assert.Equal(page1.IsSwappedOut, false); + Assert.Equal(page2.IsSwappedOut, true); + Assert.Equal(page3.IsSwappedOut, true); + Assert.Equal(page4.IsSwappedOut, false); + Assert.Equal(page5.IsSwappedOut, true); + Assert.Equal(page6.IsSwappedOut, false); + Assert.Equal(page7.IsSwappedOut, false); + + // not enough pages + bool error = false; + try + { + MemoryPage page8 = pager.ReadPage(8); + } + catch (Exception) + { + error = true; + } + Assert.Equal(error, true); + + Assert.Equal(page1.IsSwappedOut, false); + Assert.Equal(page2.Data[0], 2); + Assert.Equal(page4.Data[0], 4); + Assert.Equal(page4[1], 44); + + pager.Close(); + } + + [Fact] + static void TestPager() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 4); + + Assert.Equal(pager.PageCount, 1); + + pager.ExtendNumberOfPages(); + Assert.Equal(pager.PageCount, 2); + + MemoryPage page = pager.ReadPage(1); + page.Data[2] = 114; + page.Data[3] = 5; + page.Data[4] = 14; + + pager.WritePage(page); + MemoryPage page1 = pager.ReadPage(1); + + Assert.Equal(page.Data[2], page1.Data[2]); + Assert.Equal(page.Data[3], page1.Data[3]); + Assert.Equal(page.Data[4], page1.Data[4]); + + // it will save all dirty pages and remove all pages from recording + // after that, any MemoryPage returned from this `pager` will no longer legal to use + pager.Close(); + + pager.Open(dbPath); + // another page also with page number 1 + page1 = pager.ReadPage(1); + + // test if preventing buffer duplication + Assert.Equal(page.Data[2], page1.Data[2]); + Assert.Equal(page.Data[3], page1.Data[3]); + Assert.Equal(page.Data[4], page1.Data[4]); + + // test if the two page pointing to the same buffer + Assert.Equal(page1.Data[100], 0); + page.Data[100] = 1; + Assert.Equal(page1.Data[100], 1); + + pager.Close(); + } + + + static void AssertAtomValue(AtomValue v1, AtomValue v2) + { + Assert.Equal(v1.Type, v2.Type); + Assert.Equal(v1.CharLimit, v2.CharLimit); + Assert.Equal(v1.FloatValue, v2.FloatValue); + Assert.Equal(v1.IntegerValue, v2.IntegerValue); + Assert.Equal(v1.StringValue, v2.StringValue); + } + } +} diff --git a/tests/MiniSQL.CatalogManager.Tests/MiniSQL.CatalogManager.Tests.csproj b/tests/MiniSQL.CatalogManager.Tests/MiniSQL.CatalogManager.Tests.csproj new file mode 100644 index 0000000..7d074ec --- /dev/null +++ b/tests/MiniSQL.CatalogManager.Tests/MiniSQL.CatalogManager.Tests.csproj @@ -0,0 +1,22 @@ + + + + net5.0 + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/tests/MiniSQL.CatalogManager.Tests/UnitTest1.cs b/tests/MiniSQL.CatalogManager.Tests/UnitTest1.cs new file mode 100644 index 0000000..006efc6 --- /dev/null +++ b/tests/MiniSQL.CatalogManager.Tests/UnitTest1.cs @@ -0,0 +1,549 @@ +using System; +using Xunit; +using System.Collections.Generic; +using System.IO; +using MiniSQL.Library.Models; +using MiniSQL.CatalogManager.Controllers; +using MiniSQL.Library.Interfaces; + +namespace MiniSQL.BufferManager.Tests +{ + public class UnitTest1 + { + static ICatalogManager icatalog = new Catalog("test"); + + [Fact] + static void MainEntry() + { + Console.WriteLine("[CatalogManager] Start!"); + File.Delete($"./test.indices.dbcatalog"); + File.Delete($"./test.tables.dbcatalog"); + CheckCreate(); + CheckUpdate(); + CheckGetSchemaRecord(); + CheckValidation(); + CheckDrop(); + Console.WriteLine("[CatalogManager] Done!"); + } + + //check if the program can successfully check the validation of each kind of input statement + static bool CheckValidation() + { //since quitstatement and execfile statement are too simple,we skip them here + + Catalog func = new Catalog("test"); + + //select statement + //3 kinds, each with a true and a false version + + //select only from table without any attribute + SelectStatement select_only_table_true = new SelectStatement(); + // select_only_table_true.Condition = new Expression(); + select_only_table_true.FromTable = "Student"; + + + SelectStatement select_only_table_false = new SelectStatement(); + // select_only_table_false.Condition = new Expression(); + select_only_table_false.FromTable = "School"; + + bool test1 = func.IsValid(select_only_table_false); + bool test2 = func.IsValid(select_only_table_true); + // Console.WriteLine(" Wrong select statement that select only 1 table, expecting false:"); + // Console.WriteLine(test1); + Assert.False(test1); + // Console.WriteLine(" Right select statement that select only 1 table, expecting true:"); + // Console.WriteLine(test2); + Assert.True(test2); + + //select from table with 1 attribute + SelectStatement select_with_1_attribute_true = new SelectStatement(); + select_with_1_attribute_true.FromTable = "Student"; + select_with_1_attribute_true.Condition = new Expression(); + select_with_1_attribute_true.Condition.Operator = Operator.AtomVariable; + select_with_1_attribute_true.Condition.AttributeName = "ID"; + + + SelectStatement select_with_1_attribute_false = new SelectStatement(); + select_with_1_attribute_false.FromTable = "Student"; + select_with_1_attribute_false.Condition = new Expression(); + select_with_1_attribute_true.Condition.Operator = Operator.AtomVariable; + select_with_1_attribute_false.Condition.AttributeName = "Gender"; + + bool test3 = icatalog.IsValid(select_with_1_attribute_true); + bool test4 = icatalog.IsValid(select_with_1_attribute_false); + // Console.WriteLine("Right select statement that select with 1 attribute, expecting true:"); + // Console.WriteLine(test3); + Assert.True(test3); + // Console.WriteLine("Wrong select statement that select with 1 attribute, expecting false:"); + // Console.WriteLine(test4); + Assert.False(test4); + + // select from table with condition having 3 attribute + SelectStatement select_with_3_attribute_true = new SelectStatement(); + select_with_3_attribute_true.FromTable = "Student"; + select_with_3_attribute_true.Condition = GetExpression("ID", "Class", "Score"); + + SelectStatement select_with_3_attribute_false = new SelectStatement(); + select_with_3_attribute_false.FromTable = "Student"; + select_with_3_attribute_false.Condition = GetExpression("Gender", "Class", "Score"); + + bool test5 = icatalog.IsValid(select_with_3_attribute_true); + bool test6 = icatalog.IsValid(select_with_3_attribute_false); + // Console.WriteLine("Right select statement that select with 3 attributes, expecting true:"); + // Console.WriteLine(test5); + Assert.True(test5); + // Console.WriteLine("Wrong select statement that select with 3 attribute, expecting false:"); + // Console.WriteLine(test6); + Assert.False(test6); + + //delete statement + //3 kinds, each with a true and a false version + //almost the same as the select statement + + //delete table without any attribute + DeleteStatement delete_only_table_true = new DeleteStatement(); + delete_only_table_true.TableName = "Student"; + + DeleteStatement delete_only_table_false = new DeleteStatement(); + delete_only_table_false.TableName = "School"; + + bool tst1 = func.IsValid(delete_only_table_false); + bool tst2 = func.IsValid(delete_only_table_true); + // Console.WriteLine("Wrong delete statement that delete only table, expecting false:"); + // Console.WriteLine(tst1); + Assert.False(tst1); + // Console.WriteLine("Right delete statement that delete only table, expecting true:"); + // Console.WriteLine(tst2); + Assert.True(tst2); + + //delete from table with 1 attribute + DeleteStatement delete_with_1_attribute_true = new DeleteStatement(); + delete_with_1_attribute_true.TableName = "Student"; + delete_with_1_attribute_true.Condition = new Expression() { Operator = Operator.AtomVariable }; + delete_with_1_attribute_true.Condition.AttributeName = "ID"; + + DeleteStatement delete_with_1_attribute_false = new DeleteStatement(); + delete_with_1_attribute_false.Condition = new Expression() { Operator = Operator.AtomVariable }; + delete_with_1_attribute_false.TableName = "Student"; + delete_with_1_attribute_false.Condition.AttributeName = "Gender"; + + bool tst3 = icatalog.IsValid(delete_with_1_attribute_true); + bool tst4 = icatalog.IsValid(delete_with_1_attribute_false); + // Console.WriteLine("Right delete statement that delete with 1 attribute, expecting true:"); + // Console.WriteLine(tst3); + Assert.True(tst3); + // Console.WriteLine("Wrong delete statement that delete with 1 attribute, expecting false:"); + // Console.WriteLine(tst4); + Assert.False(tst4); + + //delete from table with 3 attribute + DeleteStatement delete_with_3_attribute_true = new DeleteStatement(); + delete_with_3_attribute_true.Condition = GetExpression("ID", "Class", "Score"); + delete_with_3_attribute_true.TableName = "Student"; + + DeleteStatement delete_with_3_attribute_false = new DeleteStatement(); + delete_with_3_attribute_false.TableName = "Student"; + delete_with_3_attribute_false.Condition = GetExpression("ID", "Gender", "Score"); + + bool tst5 = icatalog.IsValid(delete_with_3_attribute_true); + bool tst6 = icatalog.IsValid(delete_with_3_attribute_false); + // Console.WriteLine("Right delete statement that delete with 3 attribute, expecting true:"); + // Console.WriteLine(tst5); + Assert.True(tst5); + // Console.WriteLine("Wrong delete statement that delete with 3 attribute, expecting false:"); + // Console.WriteLine(tst6); + Assert.False(tst6); + + //insert statement + //3 kinds, only the first is true, others are false + + //all attributes suit + InsertStatement insert_all_suit = new InsertStatement(); + insert_all_suit.TableName = "Student"; + + //make all the values into a list + List insert_tmp1 = new List(); + AtomValue attribute_value1 = new AtomValue(); + attribute_value1.Type = AttributeTypes.Char; + attribute_value1.StringValue = "111"; + + AtomValue attribute_value2 = new AtomValue(); + attribute_value2.Type = AttributeTypes.Char; + attribute_value2.StringValue = "Lily"; + + AtomValue attribute_value3 = new AtomValue(); + attribute_value3.Type = AttributeTypes.Float; + attribute_value3.FloatValue = 80.5; + + AtomValue attribute_value4 = new AtomValue(); + attribute_value4.Type = AttributeTypes.Int; + attribute_value4.IntegerValue = 5; + + insert_tmp1.Add(attribute_value1); + insert_tmp1.Add(attribute_value2); + insert_tmp1.Add(attribute_value3); + insert_tmp1.Add(attribute_value4); + + insert_all_suit.Values = insert_tmp1; + + bool insert_test1 = icatalog.IsValid(insert_all_suit); + // Console.WriteLine("Right insert statement, expecting true:"); + // Console.WriteLine(insert_test1); + Assert.True(insert_test1); + + + //doesn't match the number of attributes + InsertStatement insert_wrong_number = new InsertStatement(); + insert_wrong_number.TableName = "Student"; + + //get the value list of only 3 attributes when 4 is the right number + insert_tmp1.RemoveAt(3); + insert_wrong_number.Values = insert_tmp1; + bool insert_test2 = icatalog.IsValid(insert_wrong_number); + // Console.WriteLine("Wrong insert statement for wrong number of attributes, expecting false:"); + // Console.WriteLine(insert_test2); + Assert.False(insert_test2); + + //doesn't match the type of attributes + InsertStatement insert_wrong_type = new InsertStatement(); + insert_wrong_type.TableName = "Student"; + + //give attribute 4 type string instead of int + AtomValue attribute_value5 = new AtomValue(); + attribute_value5.Type = AttributeTypes.Char; + attribute_value5.StringValue = "hhhh"; + insert_tmp1.Add(attribute_value5); + insert_wrong_type.Values = insert_tmp1; + bool insert_test3 = icatalog.IsValid(insert_wrong_type); + // Console.WriteLine("Wrong insert statement for wrong type of attributes, expecting false:"); + // Console.WriteLine(insert_test3); + Assert.False(insert_test3); + + + + //drop statement + //2 kind, try to drop a table or an index, each with a true and a false version + + //drop an existing table, true + DropStatement drop_table_true = new DropStatement(); + drop_table_true.TargetType = DropTarget.Table; + drop_table_true.TableName = "Student"; + bool drop_test1 = icatalog.IsValid(drop_table_true); + // Console.WriteLine("Right drop table statement, expecting true:"); + // Console.WriteLine(drop_test1); + Assert.True(drop_test1); + + //drop a table that doesn't exist, false + DropStatement drop_table_false = new DropStatement(); + drop_table_false.TargetType = DropTarget.Table; + drop_table_false.TableName = "School"; + bool drop_test2 = icatalog.IsValid(drop_table_false); + // Console.WriteLine("Wrong drop table statement, expecting false:"); + // Console.WriteLine(drop_test2); + Assert.False(drop_test2); + + //drop an existing index from the table that doesn't exist, false + DropStatement drop_index_false1 = new DropStatement(); + drop_index_false1.TargetType = DropTarget.Index; + drop_index_false1.IndexName = "index_for_student_id"; + drop_index_false1.TableName = "School"; + bool drop_test3 = icatalog.IsValid(drop_index_false1); + // Console.WriteLine("Wrong drop index statement that drop from the table that doesn't exist, expecting false:"); + // Console.WriteLine(drop_test3); + Assert.False(drop_test3); + + //drop an index that doesn't exist, false + DropStatement drop_index_false2 = new DropStatement(); + drop_index_false2.TargetType = DropTarget.Index; + drop_index_false2.IndexName = "index_wrong"; + drop_index_false2.TableName = "Student"; + bool drop_test4 = icatalog.IsValid(drop_index_false2); + // Console.WriteLine("Wrong drop index statement that drop an unknown index, expecting false:"); + // Console.WriteLine(drop_test4); + Assert.False(drop_test4); + + //drop an index that exits, true + DropStatement drop_index_true = new DropStatement(); + drop_index_true.TargetType = DropTarget.Index; + drop_index_true.IndexName = "index_for_student_id"; + drop_index_true.TableName = "Student"; + bool drop_test5 = icatalog.IsValid(drop_index_true); + // Console.WriteLine("Right drop index statement, expecting true:"); + // Console.WriteLine(drop_test5); + Assert.True(drop_test5); + + //create statement + //2 kinds, for index and for table, each with both true and wrong version + + //create a table + CreateStatement create_table_true = new CreateStatement(); + create_table_true.CreateType = CreateType.Table; + create_table_true.AttributeDeclarations = new List(){ + new AttributeDeclaration() {AttributeName = "id", Type = AttributeTypes.Int}, + new AttributeDeclaration() {AttributeName = "price", Type = AttributeTypes.Float}, + }; + create_table_true.PrimaryKey = "id"; + create_table_true.TableName = "Home"; + bool create_test1 = icatalog.IsValid(create_table_true); + // Console.WriteLine("Right create table statement, expecting true:"); + // Console.WriteLine(create_test1); + Assert.True(create_test1); + + //create an index, true + CreateStatement create_index_true = new CreateStatement(); + create_index_true.CreateType = CreateType.Index; + create_index_true.TableName = "Student"; + create_index_true.IndexName = "second_index_for_student_id"; + create_index_true.AttributeName = "ID"; + bool create_test2 = icatalog.IsValid(create_index_true); + // Console.WriteLine("Right create index statement, expecting true:"); + // Console.WriteLine(create_test2); + Assert.True(create_test2); + + //create an index that already exists, false + CreateStatement create_index_false1 = new CreateStatement(); + create_index_false1.CreateType = CreateType.Index; + create_index_false1.TableName = "Student"; + create_index_false1.IndexName = "index_for_student_id"; + create_index_false1.AttributeName = "ID"; + bool create_test3 = icatalog.IsValid(create_index_false1); + // Console.WriteLine("Wrong create index statement, expecting false:"); + // Console.WriteLine(create_test3); + Assert.False(create_test3); + + //create an index for an attribute that doesn't eixst + CreateStatement create_index_false2 = new CreateStatement(); + create_index_false2.CreateType = CreateType.Index; + create_index_false2.TableName = "Student"; + create_index_false2.IndexName = "index_for_student_home"; + create_index_false2.AttributeName = "Home"; + bool create_test4 = icatalog.IsValid(create_index_false2); + // Console.WriteLine("Wrong create index statement that is created on an attribute that does not exist, expecting false:"); + // Console.WriteLine(create_test4); + Assert.False(create_test4); + + //create an index for a table that doesn't eixst + CreateStatement create_index_false3 = new CreateStatement(); + create_index_false3.CreateType = CreateType.Index; + create_index_false3.TableName = "Home"; + create_index_false3.IndexName = "index_for_student_house"; + create_index_false3.AttributeName = "Street"; + bool create_test5 = icatalog.IsValid(create_index_false3); + // Console.WriteLine("Wrong create index statement that is created on a table that doesn't exist, expecting false:"); + // Console.WriteLine(create_test5); + Assert.False(create_test5); + + return true; + } + + static bool CheckCreate() + { + //test create statement including index and table + + //make a create statement for table + CreateStatement test_create_table = new CreateStatement(); + test_create_table.CreateType = CreateType.Table; + test_create_table.TableName = "Student"; + test_create_table.IndexName = ""; + test_create_table.AttributeName = ""; + + List temp = new List(); + AttributeDeclaration student_name = new AttributeDeclaration(); + student_name.AttributeName = "Name"; + student_name.CharLimit = 10; + student_name.Type = AttributeTypes.Char; + student_name.IsUnique = false; + AttributeDeclaration student_score = new AttributeDeclaration(); + student_score.AttributeName = "Score"; + student_score.Type = AttributeTypes.Float; + student_score.IsUnique = false; + AttributeDeclaration student_class = new AttributeDeclaration(); + student_class.AttributeName = "Class"; + student_class.Type = AttributeTypes.Int; + student_class.IsUnique = false; + AttributeDeclaration student_ID = new AttributeDeclaration(); + student_ID.AttributeName = "ID"; + student_ID.Type = AttributeTypes.Char; + student_ID.CharLimit = 10; + student_ID.IsUnique = true; + temp.Add(student_ID); + temp.Add(student_name); + temp.Add(student_score); + temp.Add(student_class); + test_create_table.AttributeDeclarations = temp; + test_create_table.PrimaryKey = "ID"; + //return whether we have successfully created the statement + bool test1 = icatalog.TryCreateStatement(test_create_table, 0); + // Console.WriteLine("Create table, expecting true:"); + // Console.WriteLine(test1); + Assert.True(test1); + + //make a create statement for index + CreateStatement test_create_index = new CreateStatement(); + test_create_index.CreateType = CreateType.Index; + test_create_index.TableName = "Student"; + test_create_index.IsUnique = true; + test_create_index.IndexName = "index_for_student_id"; + test_create_index.AttributeName = "ID"; + test_create_index.AttributeDeclarations = new List() + { new AttributeDeclaration() { AttributeName = "priKey", Type = AttributeTypes.Char, CharLimit = 20 } }; + test_create_index.PrimaryKey = "priKey"; + bool test2 = icatalog.TryCreateStatement(test_create_index, 1); + // Console.WriteLine("Create index1, expecting true:"); + // Console.WriteLine(test2); + Assert.True(test2); + + CreateStatement test_create_index2 = new CreateStatement(); + test_create_index2.CreateType = CreateType.Index; + test_create_index2.TableName = "Student"; + test_create_index2.IsUnique = true; + test_create_index2.IndexName = "index2"; + test_create_index2.AttributeName = "ID"; + test_create_index2.AttributeDeclarations = new List() + { new AttributeDeclaration() { AttributeName = "priKey2", Type = AttributeTypes.Char, CharLimit = 20 } }; + test_create_index2.PrimaryKey = "priKey2"; + bool test3 = icatalog.TryCreateStatement(test_create_index2, 7); + // Console.WriteLine("Create index2, expecting true:"); + // Console.WriteLine(test3); + Assert.True(test3); + + return true; + } + + static bool CheckDrop() + { + //make a drop statement for a index + //delete this index before delete the table, return true + DropStatement test_drop_index = new DropStatement(); + test_drop_index.TargetType = DropTarget.Index; + test_drop_index.IndexName = "index_for_student_id"; + bool test4 = icatalog.TryDropStatement(test_drop_index); + // Console.WriteLine("Delete Index1, expecting true:"); + // Console.WriteLine(test4); + Assert.True(test4); + + //make a drop statement for a table + //delete this table and its assotiated indices, return true + DropStatement test_drop_table = new DropStatement(); + test_drop_table.TargetType = DropTarget.Table; + test_drop_table.TableName = "Student"; + bool test3 = icatalog.TryDropStatement(test_drop_table); + // Console.WriteLine("Delete table, expecting true:"); + // Console.WriteLine(test3); + Assert.True(test3); + + //make a drop statement for a index + //delete this + DropStatement test_drop_index2 = new DropStatement(); + test_drop_index2.TargetType = DropTarget.Index; + test_drop_index2.IndexName = "index2"; + bool test5 = icatalog.TryDropStatement(test_drop_index2); + // Console.WriteLine("Delete index2 after deleting table, expecting false:"); + // Console.WriteLine(test5); + Assert.False(test5); + + return true; + } + + + //check whether we can successfully return the schema record of a table or an index + static bool CheckGetSchemaRecord() + { + + SchemaRecord target_table = icatalog.GetTableSchemaRecord("Student"); + Console.WriteLine("Schema of Table"); + Console.WriteLine(target_table.Name); + Console.WriteLine(target_table.RootPage); + Console.WriteLine(target_table.Type); + Console.WriteLine(target_table.SQL.PrimaryKey); + Console.WriteLine(target_table.SQL.TableName); + Console.WriteLine(target_table.SQL.Type); + + SchemaRecord target_index = icatalog.GetIndexSchemaRecord("index_for_student_id"); + Console.WriteLine("Schema of Index"); + Console.WriteLine(target_index.Name); + Console.WriteLine(target_index.RootPage); + Console.WriteLine(target_index.Type); + Console.WriteLine(target_index.SQL.IndexName); + Console.WriteLine(target_index.SQL.IsUnique); + Console.WriteLine(target_index.SQL.Type); + + List target_indices = icatalog.GetIndicesSchemaRecord("Student"); + for (int i = 0; i < target_indices.Count; i++) + { + Console.WriteLine("Schema of Indices"); + Console.WriteLine(target_indices[i].Name); + Console.WriteLine(target_indices[i].RootPage); + Console.WriteLine(target_indices[i].Type); + Console.WriteLine(target_indices[i].SQL.IndexName); + Console.WriteLine(target_indices[i].SQL.IsUnique); + Console.WriteLine(target_indices[i].SQL.Type); + } + return true; + + } + + static bool CheckUpdate() + { + //update the rootpage of a table + SchemaRecord table_before = icatalog.GetTableSchemaRecord("Student"); + Console.WriteLine(table_before.RootPage); + icatalog.TryUpdateSchemaRecord("Student", 2); + SchemaRecord table_after = icatalog.GetTableSchemaRecord("Student"); + Console.WriteLine(table_after.RootPage); + Assert.Equal(2, table_after.RootPage); + + //update the rootpage of an index + SchemaRecord index_before = icatalog.GetIndexSchemaRecord("index_for_student_id"); + Console.WriteLine(index_before.RootPage); + icatalog.TryUpdateSchemaRecord("index_for_student_id", 3); + SchemaRecord index_after = icatalog.GetIndexSchemaRecord("index_for_student_id"); + Console.WriteLine(index_after.RootPage); + Assert.Equal(3, index_after.RootPage); + + //try to update the table or index that does not exist + //will print false + bool test1 = icatalog.TryUpdateSchemaRecord("HHH", 5); + bool test2 = icatalog.TryUpdateSchemaRecord("hhh", 6); + Console.WriteLine(test1); + Console.WriteLine(test2); + Assert.False(test1); + Assert.False(test2); + + return true; + } + + // get test Expression Tree + private static Expression GetExpression(string name1, string name2, string name3) + { + Expression root = new Expression(); + // make condition tree + root.Operator = Operator.And; + Expression secondAnd = new Expression() { Operator = Operator.And }; + Expression idOperator = new Expression() { Operator = Operator.Equal }; + Expression idExp = new Expression() { Operator = Operator.AtomVariable, AttributeName = name1 }; + Expression temp1 = new Expression() + { Operator = Operator.AtomConcreteValue, ConcreteValue = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 10 } }; + idOperator.LeftOperand = idExp; + idOperator.RightOperand = temp1; + Expression classOperator = new Expression() { Operator = Operator.MoreThan }; + Expression classExp = new Expression() { Operator = Operator.AtomVariable, AttributeName = name2 }; + Expression temp2 = new Expression() + { Operator = Operator.AtomConcreteValue, ConcreteValue = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 10 } }; + classOperator.LeftOperand = temp2; + classOperator.RightOperand = classExp; + Expression scoreOperator = new Expression() { Operator = Operator.LessThanOrEqualTo }; + Expression scoreExp = new Expression() { Operator = Operator.AtomVariable, AttributeName = name3 }; + Expression temp3 = new Expression() + { Operator = Operator.AtomConcreteValue, ConcreteValue = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 10 } }; + scoreOperator.LeftOperand = temp3; + scoreOperator.RightOperand = scoreExp; + // connect tree trunk + root.LeftOperand = secondAnd; + root.RightOperand = scoreOperator; + secondAnd.LeftOperand = idOperator; + secondAnd.RightOperand = classOperator; + + return root; + } + } +} diff --git a/tests/MiniSQL.IndexManager.Tests/MiniSQL.IndexManager.Tests.csproj b/tests/MiniSQL.IndexManager.Tests/MiniSQL.IndexManager.Tests.csproj new file mode 100644 index 0000000..4ddcd53 --- /dev/null +++ b/tests/MiniSQL.IndexManager.Tests/MiniSQL.IndexManager.Tests.csproj @@ -0,0 +1,21 @@ + + + + net5.0 + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/tests/MiniSQL.IndexManager.Tests/UnitTest1.cs b/tests/MiniSQL.IndexManager.Tests/UnitTest1.cs new file mode 100644 index 0000000..102429a --- /dev/null +++ b/tests/MiniSQL.IndexManager.Tests/UnitTest1.cs @@ -0,0 +1,1264 @@ +using System; +using System.Collections.Generic; +using System.IO; +using MiniSQL.BufferManager.Controllers; +using MiniSQL.BufferManager.Models; +using MiniSQL.IndexManager.Controllers; +using MiniSQL.IndexManager.Models; +using MiniSQL.IndexManager.Utilities; +using MiniSQL.Library.Exceptions; +using MiniSQL.Library.Models; +using Xunit; + +namespace MiniSQL.IndexManager.Tests +{ + public class UnitTest1 + { + // Fixed issue at the #6 stage + [Fact] + static void BugTest3() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + BTreeNode root = null; + LeafTableCell result = null; + // 1 + // DBRecord record = GetTestBRecord(74396264); + // DBRecord keyRecord = GetTestBRecord(74396264); + DBRecord record = GetTestBRecord(1); + DBRecord keyRecord = GetTestBRecord(1); + root = controller.InsertCell(root, keyRecord, record); + // 2 + // record = GetTestBRecord(1766307441); + // keyRecord = GetTestBRecord(1766307441); + record = GetTestBRecord(7); + keyRecord = GetTestBRecord(7); + root = controller.InsertCell(root, keyRecord, record); + // 3 + // record = GetTestBRecord(2025306881); + // keyRecord = GetTestBRecord(2025306881); + record = GetTestBRecord(8); + keyRecord = GetTestBRecord(8); + root = controller.InsertCell(root, keyRecord, record); + // 4 + // record = GetTestBRecord(147488698); + // keyRecord = GetTestBRecord(147488698); + record = GetTestBRecord(2); + keyRecord = GetTestBRecord(2); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + // 5 + // record = GetTestBRecord(1109110087); + // keyRecord = GetTestBRecord(1109110087); + record = GetTestBRecord(4); + keyRecord = GetTestBRecord(4); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + // test 5 + // keyRecord = GetTestBRecord(1109110087); + keyRecord = GetTestBRecord(4); + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + // Assert.Equal(==, result.Key.GetValues()[0].IntegerValue 1109110087); + Assert.Equal(4, result.Key.GetValues()[0].IntegerValue); + + // 6 + // record = GetTestBRecord(1163206015); + // keyRecord = GetTestBRecord(1163206015); + record = GetTestBRecord(5); + keyRecord = GetTestBRecord(5); + // ISSUE HERE + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + // 7 + // record = GetTestBRecord(1485715653); + // keyRecord = GetTestBRecord(1485715653); + record = GetTestBRecord(6); + keyRecord = GetTestBRecord(6); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + // 8 + // record = GetTestBRecord(1087082570); + // keyRecord = GetTestBRecord(1087082570); + record = GetTestBRecord(3); + keyRecord = GetTestBRecord(3); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + pager.Close(); + } + + [Fact] + static void BugTest1() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + BTreeNode root = null; + LeafTableCell result = null; + + DBRecord record = GetTestBRecord(76767785); + DBRecord keyRecord = GetTestBRecord(76767785); + root = controller.InsertCell(root, keyRecord, record); + + record = GetTestBRecord(1922063022); + keyRecord = GetTestBRecord(1922063022); + root = controller.InsertCell(root, keyRecord, record); + + record = GetTestBRecord(514874720); + keyRecord = GetTestBRecord(514874720); + root = controller.InsertCell(root, keyRecord, record); + + record = GetTestBRecord(724803552); + keyRecord = GetTestBRecord(724803552); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(1219882375); + keyRecord = GetTestBRecord(1219882375); + root = controller.InsertCell(root, keyRecord, record); + + keyRecord = GetTestBRecord(724803552); + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(724803552, result.Key.GetValues()[0].IntegerValue); + + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(681446986); + keyRecord = GetTestBRecord(681446986); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(1427789753); + keyRecord = GetTestBRecord(1427789753); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(1066176166); + keyRecord = GetTestBRecord(1066176166); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + pager.Close(); + } + + [Fact] + static void Bugtest2() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + BTreeNode root = null; + LeafTableCell result = null; + + DBRecord record = GetTestBRecord(660132168); + DBRecord keyRecord = GetTestBRecord(660132168); + root = controller.InsertCell(root, keyRecord, record); + + record = GetTestBRecord(2007593075); + keyRecord = GetTestBRecord(2007593075); + root = controller.InsertCell(root, keyRecord, record); + + record = GetTestBRecord(356456016); + keyRecord = GetTestBRecord(356456016); + root = controller.InsertCell(root, keyRecord, record); + + record = GetTestBRecord(32731844); + keyRecord = GetTestBRecord(32731844); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(159431057); + keyRecord = GetTestBRecord(159431057); + root = controller.InsertCell(root, keyRecord, record); + + keyRecord = GetTestBRecord(660132168); + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(660132168, result.Key.GetValues()[0].IntegerValue); + + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(991596943); + keyRecord = GetTestBRecord(991596943); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(794643883); + keyRecord = GetTestBRecord(794643883); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + record = GetTestBRecord(1158712065); + keyRecord = GetTestBRecord(1158712065); + root = controller.InsertCell(root, keyRecord, record); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + pager.Close(); + } + + [Fact] + static void TestExpressionDelete() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + BTreeNode root = null; + + Expression expression = GetAndsExpression(); + + for (int i = 1; i < 30; i++) + { + DBRecord record = GetTestRecord_expression(i, "str", (float)3.3); + DBRecord key = GetTestKey_expression(i); + if (i == 17 || i == 19) + { + record = GetTestRecord_expression(i, "str", (float)10.5); + } + else if (i == 20 || i == 23) + { + record = GetTestRecord_expression(i, "www", (float)1.3); + } + root = controller.InsertCell(root, key, record); + } + List attributeNames = new List(); + + AttributeDeclaration attribute_1 = new AttributeDeclaration(); + attribute_1.AttributeName = "a"; + attribute_1.IsUnique = true; + attributeNames.Add(attribute_1); + + AttributeDeclaration attribute_2 = new AttributeDeclaration(); + attribute_2.AttributeName = "b"; + attribute_2.IsUnique = false; + attributeNames.Add(attribute_2); + + AttributeDeclaration attribute_3 = new AttributeDeclaration(); + attribute_3.AttributeName = "c"; + attribute_3.IsUnique = false; + attributeNames.Add(attribute_3); + + root = controller.DeleteCells(root, expression, "a", attributeNames); + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + pager.Close(); + } + + [Fact] + static void TestExpressionFind() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + BTreeNode root = null; + List result = null; + + Expression expression = GetAndsExpression(); + + for (int i = 1; i < 30; i++) + { + DBRecord record = GetTestRecord_expression(i, "str", (float)3.3); + DBRecord key = GetTestKey_expression(i); + if (i == 17 || i == 19) + { + record = GetTestRecord_expression(i, "str", (float)10.5); + } + else if (i == 20 || i == 23) + { + record = GetTestRecord_expression(i, "www", (float)1.3); + } + root = controller.InsertCell(root, key, record); + } + List attributeNames = new List(); + + AttributeDeclaration attribute_1 = new AttributeDeclaration(); + attribute_1.AttributeName = "a"; + attribute_1.IsUnique = true; + attributeNames.Add(attribute_1); + + AttributeDeclaration attribute_2 = new AttributeDeclaration(); + attribute_2.AttributeName = "b"; + attribute_2.IsUnique = false; + attributeNames.Add(attribute_2); + + AttributeDeclaration attribute_3 = new AttributeDeclaration(); + attribute_3.AttributeName = "c"; + attribute_3.IsUnique = false; + attributeNames.Add(attribute_3); + + result = controller.FindCells(root, expression, "a", attributeNames); + + foreach (var cell in result) + { + LeafTableCell leafTableCell = (LeafTableCell)cell; + Console.Write(leafTableCell.DBRecord.GetValues()[0].IntegerValue); + Console.Write("|"); + Console.Write(leafTableCell.DBRecord.GetValues()[1].StringValue); + Console.Write("|"); + Console.Write(leafTableCell.DBRecord.GetValues()[2].FloatValue); + Console.WriteLine(); + } + + pager.Close(); + } + + private static DBRecord GetTestRecord_expression(int value_1, string value_2, float value_3) + { + List values = new List(); + AtomValue value1 = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = value_1 }; + AtomValue value2 = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 5, StringValue = value_2 }; + AtomValue value3 = new AtomValue() { Type = AttributeTypes.Float, FloatValue = value_3 }; + values.Add(value1); + values.Add(value2); + values.Add(value3); + DBRecord record = new DBRecord(values); + + return record; + } + + private static DBRecord GetTestKey_expression(int value_1) + { + List values = new List(); + AtomValue value1 = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = value_1 }; + values.Add(value1); + DBRecord record = new DBRecord(values); + return record; + } + + private static Expression GetAndsExpression() + { + // __tree structure__ + // and 1 + // and 2,> 3 + // <= 4, <= 5, 6.6 6, c 7 + // 15 8, a, 9, b 10, "str" 11 + + // 32 + Expression node8 = new Expression(); + node8.Operator = Operator.AtomConcreteValue; + node8.ConcreteValue = new AtomValue(); + node8.ConcreteValue.Type = AttributeTypes.Int; + node8.ConcreteValue.IntegerValue = 15; + // a + Expression node9 = new Expression(); + node9.Operator = Operator.AtomVariable; + node9.AttributeName = "a"; + // b + Expression node10 = new Expression(); + node10.Operator = Operator.AtomVariable; + node10.AttributeName = "b"; + // "str" + Expression node11 = new Expression(); + node11.Operator = Operator.AtomConcreteValue; + node11.ConcreteValue = new AtomValue(); + node11.ConcreteValue.Type = AttributeTypes.Char; + node11.ConcreteValue.CharLimit = 5; + node11.ConcreteValue.StringValue = "str"; + // <= + Expression node4 = new Expression(); + node4.Operator = Operator.LessThanOrEqualTo; + node4.LeftOperand = node8; + node4.RightOperand = node9; + // <= + Expression node5 = new Expression(); + node5.Operator = Operator.LessThanOrEqualTo; + node5.LeftOperand = node10; + node5.RightOperand = node11; + // 6.6 + Expression node6 = new Expression(); + node6.Operator = Operator.AtomConcreteValue; + node6.ConcreteValue = new AtomValue(); + node6.ConcreteValue.Type = AttributeTypes.Float; + node6.ConcreteValue.FloatValue = 6.6; + // c + Expression node7 = new Expression(); + node7.Operator = Operator.AtomVariable; + node7.AttributeName = "c"; + // and + Expression node2 = new Expression(); + node2.Operator = Operator.And; + node2.LeftOperand = node4; + node2.RightOperand = node5; + //> + Expression node3 = new Expression(); + node3.Operator = Operator.MoreThan; + node3.LeftOperand = node6; + node3.RightOperand = node7; + // and + Expression node1 = new Expression(); + node1.Operator = Operator.And; + node1.LeftOperand = node2; + node1.RightOperand = node3; + + return node1; + } + + [Fact] + static void TestBTreeDelete() + { + + LeafTableCell result = null; + // init record + DBRecord record_0 = GetTestBRecord(100); + DBRecord record_1 = GetTestBRecord(101); + DBRecord record_2 = GetTestBRecord(102); + DBRecord record_3 = GetTestBRecord(103); + DBRecord record_4 = GetTestBRecord(104); + DBRecord record_5 = GetTestBRecord(105); + DBRecord record_6 = GetTestBRecord(106); + DBRecord record_7 = GetTestBRecord(107); + DBRecord record_8 = GetTestBRecord(108); + + DBRecord keyRecord_0 = GetTestBRecord(1); + DBRecord keyRecord_1 = GetTestBRecord(2); + DBRecord keyRecord_2 = GetTestBRecord(3); + DBRecord keyRecord_3 = GetTestBRecord(4); + DBRecord keyRecord_4 = GetTestBRecord(5); + DBRecord keyRecord_5 = GetTestBRecord(6); + DBRecord keyRecord_6 = GetTestBRecord(7); + DBRecord keyRecord_7 = GetTestBRecord(8); + DBRecord keyRecord_8 = GetTestBRecord(9); + + + // init key + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + BTreeNode root = null; + //0 + root = controller.InsertCell(root, keyRecord_0, record_0); + //1 + root = controller.InsertCell(root, keyRecord_1, record_1); + //2 + root = controller.InsertCell(root, keyRecord_2, record_2); + //3 + root = controller.InsertCell(root, keyRecord_3, record_3); + //4 + root = controller.InsertCell(root, keyRecord_4, record_4); + //5 + root = controller.InsertCell(root, keyRecord_5, record_5); + //6 + root = controller.InsertCell(root, keyRecord_6, record_6); + + //Delete test; + + //6 + root = controller.Delete(keyRecord_6, root); + result = (LeafTableCell)controller.FindCell(keyRecord_6, root); + Assert.Null(result); + + //5 + root = controller.Delete(keyRecord_5, root); + result = (LeafTableCell)controller.FindCell(keyRecord_5, root); + Assert.Null(result); + + //4 + root = controller.Delete(keyRecord_4, root); + result = (LeafTableCell)controller.FindCell(keyRecord_4, root); + Assert.Null(result); + + + //3 + root = controller.Delete(keyRecord_3, root); + result = (LeafTableCell)controller.FindCell(keyRecord_3, root); + Assert.Null(result); + + //2 + root = controller.Delete(keyRecord_2, root); + result = (LeafTableCell)controller.FindCell(keyRecord_2, root); + Assert.Null(result); + + //1 + root = controller.Delete(keyRecord_1, root); + result = (LeafTableCell)controller.FindCell(keyRecord_1, root); + Assert.Null(result); + + + //0 + root = controller.Delete(keyRecord_0, root); + result = (LeafTableCell)controller.FindCell(keyRecord_0, root); + Assert.Null(result); + + + //insert after delete + root = controller.InsertCell(root, keyRecord_0, record_0); + result = (LeafTableCell)controller.FindCell(keyRecord_0, root); + Assert.NotNull(result); + Assert.Equal(1, result.Key.GetValues()[0].IntegerValue); + + root = controller.InsertCell(root, keyRecord_7, record_7); + result = (LeafTableCell)controller.FindCell(keyRecord_7, root); + Assert.NotNull(result); + Assert.Equal(8, result.Key.GetValues()[0].IntegerValue); + + + root = controller.InsertCell(root, keyRecord_6, record_6); + result = (LeafTableCell)controller.FindCell(keyRecord_6, root); + Assert.NotNull(result); + Assert.Equal(7, result.Key.GetValues()[0].IntegerValue); + + pager.Close(); + } + + [Fact] + static void HardTestForBTree() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList, 4); + BTreeNode root = null; + LeafTableCell result = null; + + //Construct BTree + for (int i = 1; i < 20; i++) + { + DBRecord record = GetTestBRecord(i + 100); + DBRecord keyRecord = GetTestBRecord(i); + root = controller.InsertCell(root, keyRecord, record); + + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); + + } + // test inserting records with repeated primary keys + DBRecord record_D = GetTestBRecord(103); + DBRecord keyRecord_D = GetTestBRecord(3); + bool isError = false; + try + { + root = controller.InsertCell(root, keyRecord_D, record_D); + } + catch (RepeatedKeyException) + { + isError = true; + } + Assert.True(isError); + + isError = false; + record_D = GetTestBRecord(105); + keyRecord_D = GetTestBRecord(5); + try + { + root = controller.InsertCell(root, keyRecord_D, record_D); + } + catch (RepeatedKeyException) + { + isError = true; + } + + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + //find all + for (int i = 1; i < 20; i++) + { + DBRecord keyRecord = GetTestBRecord(i); + + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); + + } + + //delete + for (int i = 10; i < 20; i++) + { + DBRecord keyRecord = GetTestBRecord(i); + root = controller.Delete(keyRecord, root); + + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.Null(result); + + for (int m = 1; m < 10; m++) + { + DBRecord keyRecord_check = GetTestBRecord(m); + + result = (LeafTableCell)controller.FindCell(keyRecord_check, root); + Assert.NotNull(result); + Assert.Equal(m, result.Key.GetValues()[0].IntegerValue); + + } + } + BTreeNodeHelper.VisualizeIntegerTree(pager, root); + + //find others + for (int i = 1; i < 10; i++) + { + DBRecord keyRecord = GetTestBRecord(i); + + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); + + } + + + //insert after delete + for (int i = 10; i < 20; i++) + { + DBRecord record = GetTestBRecord(i + 100); + DBRecord keyRecord = GetTestBRecord(i); + root = controller.InsertCell(root, keyRecord, record); + + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); + + } + + //find all + for (int i = 1; i < 20; i++) + { + DBRecord keyRecord = GetTestBRecord(i); + + result = (LeafTableCell)controller.FindCell(keyRecord, root); + Assert.NotNull(result); + Assert.Equal(i, result.Key.GetValues()[0].IntegerValue); + + } + + pager.Close(); + } + + [Fact] + static void TestBTreeInsert() + { + LeafTableCell result = null; + // init record + DBRecord record_0 = GetTestBRecord(100); + DBRecord record_1 = GetTestBRecord(101); + DBRecord record_2 = GetTestBRecord(102); + DBRecord record_3 = GetTestBRecord(103); + DBRecord record_4 = GetTestBRecord(104); + DBRecord record_5 = GetTestBRecord(105); + DBRecord record_6 = GetTestBRecord(106); + DBRecord record_7 = GetTestBRecord(107); + + DBRecord keyRecord_0 = GetTestBRecord(1); + DBRecord keyRecord_1 = GetTestBRecord(2); + DBRecord keyRecord_2 = GetTestBRecord(3); + DBRecord keyRecord_3 = GetTestBRecord(4); + DBRecord keyRecord_4 = GetTestBRecord(5); + DBRecord keyRecord_5 = GetTestBRecord(6); + DBRecord keyRecord_6 = GetTestBRecord(7); + + + // init key + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + Pager pager = new Pager(dbPath); + FreeList freeList = new FreeList(pager); + BTreeController controller = new BTreeController(pager, freeList); + + BTreeNode root = null; + root = controller.InsertCell(root, keyRecord_0, record_0); + result = (LeafTableCell)controller.FindCell(keyRecord_0, root); + Assert.NotNull(result); + Assert.Equal(1, result.Key.GetValues()[0].IntegerValue); + //1 + root = controller.InsertCell(root, keyRecord_1, record_1); + result = (LeafTableCell)controller.FindCell(keyRecord_1, root); + Assert.NotNull(result); + Assert.Equal(2, result.Key.GetValues()[0].IntegerValue); + //2 + root = controller.InsertCell(root, keyRecord_2, record_2); + result = (LeafTableCell)controller.FindCell(keyRecord_2, root); + Assert.NotNull(result); + Assert.Equal(3, result.Key.GetValues()[0].IntegerValue); + //3 + root = controller.InsertCell(root, keyRecord_3, record_3); + result = (LeafTableCell)controller.FindCell(keyRecord_3, root); + Assert.NotNull(result); + Assert.Equal(4, result.Key.GetValues()[0].IntegerValue); + //4 + root = controller.InsertCell(root, keyRecord_4, record_4); + result = (LeafTableCell)controller.FindCell(keyRecord_4, root); + Assert.NotNull(result); + Assert.Equal(5, result.Key.GetValues()[0].IntegerValue); + //5 + root = controller.InsertCell(root, keyRecord_5, record_5); + result = (LeafTableCell)controller.FindCell(keyRecord_5, root); + Assert.NotNull(result); + Assert.Equal(6, result.Key.GetValues()[0].IntegerValue); + + //6 + root = controller.InsertCell(root, keyRecord_6, record_6); + result = (LeafTableCell)controller.FindCell(keyRecord_6, root); + Assert.NotNull(result); + Assert.Equal(7, result.Key.GetValues()[0].IntegerValue); + //Find + + result = (LeafTableCell)controller.FindCell(keyRecord_0, root); + Assert.NotNull(result); + Assert.Equal(1, result.Key.GetValues()[0].IntegerValue); + + result = (LeafTableCell)controller.FindCell(keyRecord_1, root); + Assert.NotNull(result); + Assert.Equal(2, result.Key.GetValues()[0].IntegerValue); + + result = (LeafTableCell)controller.FindCell(keyRecord_2, root); + Assert.NotNull(result); + Assert.Equal(3, result.Key.GetValues()[0].IntegerValue); + + result = (LeafTableCell)controller.FindCell(keyRecord_3, root); + Assert.NotNull(result); + Assert.Equal(4, result.Key.GetValues()[0].IntegerValue); + + result = (LeafTableCell)controller.FindCell(keyRecord_4, root); + Assert.NotNull(result); + Assert.Equal(5, result.Key.GetValues()[0].IntegerValue); + + result = (LeafTableCell)controller.FindCell(keyRecord_5, root); + Assert.NotNull(result); + Assert.Equal(6, result.Key.GetValues()[0].IntegerValue); + + result = (LeafTableCell)controller.FindCell(keyRecord_6, root); + Assert.NotNull(result); + Assert.Equal(7, result.Key.GetValues()[0].IntegerValue); + + pager.Close(); + } + + + [Fact] + static void TestFreeList() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 100); + + List pageList = new List(); + pageList.Add(pager.GetNewPage()); // page #2 + pageList.Add(pager.GetNewPage()); // page #3 + pageList.Add(pager.GetNewPage()); // page #4 + pageList.Add(pager.GetNewPage()); // page #5 + + FreeList freeList = new FreeList(pager); + + // test initialization + MemoryPage newPage = null; + newPage = freeList.AllocatePage(); // freeList is now empty + Assert.Null(newPage); + + // recycle pages + // MemoryPage tempPage = pager.ReadPage(3); + freeList.RecyclePage(pageList[2]); // freeList->4 + freeList.RecyclePage(pageList[1]); // freeList->3->4 + freeList.RecyclePage(pageList[3]); // freeList->5->3->4 + + // fetch page from free list + newPage = freeList.AllocatePage(); // freeList->3->4 + Assert.Equal(5, newPage.PageNumber); + newPage = freeList.AllocatePage(); // freeList->4 + Assert.Equal(3, newPage.PageNumber); + + // recycle a page + freeList.RecyclePage(pageList[3]); // freeList->5->4 + + // fetch remaining pages + newPage = freeList.AllocatePage(); // freeList->4 + Assert.Equal(5, newPage.PageNumber); + newPage = freeList.AllocatePage(); // freeList->null + Assert.Equal(4, newPage.PageNumber); + newPage = freeList.AllocatePage(); // freeList->null + Assert.Null(newPage); + + pager.Close(); + } + + [Fact] + static void TestInsertIntoAndDeletionInsideBTreeNode() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + + MemoryPage page = pager.ReadPage(1); + + BTreeNode node = new BTreeNode(page, PageTypes.InternalIndexPage); + + + // `keys` := (1, 6, 2, 5, 3, 4) + List keys = new List(); + keys.Add(GetTestBRecord(1)); + keys.Add(GetTestBRecord(6)); + keys.Add(GetTestBRecord(2)); + keys.Add(GetTestBRecord(5)); + keys.Add(GetTestBRecord(3)); + keys.Add(GetTestBRecord(4)); + + // `cells` := ((1, 0), (6, 1), (2, 2), (5, 3), (3, 4), (4, 5)) + List cells = new List(); + cells.Add(new InternalIndexCell(keys[0], 114, GetTestBRecord(0))); + cells.Add(new InternalIndexCell(keys[1], 114, GetTestBRecord(1))); + cells.Add(new InternalIndexCell(keys[2], 114, GetTestBRecord(2))); + cells.Add(new InternalIndexCell(keys[3], 114, GetTestBRecord(3))); + cells.Add(new InternalIndexCell(keys[4], 114, GetTestBRecord(4))); + cells.Add(new InternalIndexCell(keys[5], 114, GetTestBRecord(5))); + + byte[] raw = cells[0].Pack(); + InternalIndexCell cellClone = new InternalIndexCell(raw, 0); + + node.InsertBTreeCell(cells[0]); + node.InsertBTreeCell(cells[1]); + node.InsertBTreeCell(cells[2]); + node.InsertBTreeCell(cells[3]); + node.InsertBTreeCell(cells[4]); + node.InsertBTreeCell(cells[5]); + + List offsets = node.CellOffsetArray; + List clonecells = new List(); + clonecells.Add((InternalIndexCell)node.GetBTreeCell(offsets[0])); + clonecells.Add((InternalIndexCell)node.GetBTreeCell(offsets[1])); + clonecells.Add((InternalIndexCell)node.GetBTreeCell(offsets[2])); + clonecells.Add((InternalIndexCell)node.GetBTreeCell(offsets[3])); + clonecells.Add((InternalIndexCell)node.GetBTreeCell(offsets[4])); + clonecells.Add((InternalIndexCell)node.GetBTreeCell(offsets[5])); + + List cloneCellKey = clonecells[0].Key.GetValues(); + + // all cells (not the list `cells`) inside `node`: + // ((1, 0), (2, 2), (3, 4), (4, 5), (5, 3), (6, 1)) + // they are all pointing to page #114 + + // check if the keys are stored in ascending order + Assert.Equal(1, node.GetBTreeCell(offsets[0]).Key.GetValues()[0].IntegerValue); + Assert.Equal(2, node.GetBTreeCell(offsets[1]).Key.GetValues()[0].IntegerValue); + Assert.Equal(3, node.GetBTreeCell(offsets[2]).Key.GetValues()[0].IntegerValue); + Assert.Equal(4, node.GetBTreeCell(offsets[3]).Key.GetValues()[0].IntegerValue); + Assert.Equal(5, node.GetBTreeCell(offsets[4]).Key.GetValues()[0].IntegerValue); + Assert.Equal(6, node.GetBTreeCell(offsets[5]).Key.GetValues()[0].IntegerValue); + + List tmpAtomList = null; + + // check if `node` could be iterated by "foreach" statement + int i = 1; + foreach (var iteratedCell in node) + { + tmpAtomList = iteratedCell.Key.GetValues(); + Assert.Equal(tmpAtomList[0].IntegerValue, i); + i++; + } + + // check node indexing + AssertCell(node[0], cells[0]); + AssertCell(node[1], cells[2]); + + BTreeCell cell; + ushort offset; + int indexInOffsetArray; + + // find by the keys below and check if it returns currect cells + // key 6: value 1 + (cell, offset, indexInOffsetArray) = node.FindBTreeCell(keys[1]); + tmpAtomList = ((InternalIndexCell)cell).Key.GetValues(); + Assert.Equal(6, tmpAtomList[0].IntegerValue); + tmpAtomList = ((InternalIndexCell)cell).PrimaryKey.GetValues(); + Assert.Equal(1, tmpAtomList[0].IntegerValue); + // key 5: value 3 + (cell, offset, indexInOffsetArray) = node.FindBTreeCell(keys[3]); + tmpAtomList = ((InternalIndexCell)cell).Key.GetValues(); + Assert.Equal(5, tmpAtomList[0].IntegerValue); + tmpAtomList = ((InternalIndexCell)cell).PrimaryKey.GetValues(); + Assert.Equal(3, tmpAtomList[0].IntegerValue); + // key 2: value 2 + (cell, offset, indexInOffsetArray) = node.FindBTreeCell(keys[2]); + tmpAtomList = cell.Key.GetValues(); + Assert.Equal(2, tmpAtomList[0].IntegerValue); + tmpAtomList = ((InternalIndexCell)cell).PrimaryKey.GetValues(); + Assert.Equal(2, tmpAtomList[0].IntegerValue); + + // delete cell with key == 2 + node.DeleteBTreeCell(offset); + + // check deletion + offsets = node.CellOffsetArray; + tmpAtomList = node.GetBTreeCell(offsets[0]).Key.GetValues(); + Assert.Equal(1, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[1]).Key.GetValues(); + Assert.Equal(3, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[2]).Key.GetValues(); + Assert.Equal(4, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[3]).Key.GetValues(); + Assert.Equal(5, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[4]).Key.GetValues(); + Assert.Equal(6, tmpAtomList[0].IntegerValue); + + // delete cell with key == 4 + node.DeleteBTreeCell(offsets[2]); + + // check deletion + offsets = node.CellOffsetArray; + tmpAtomList = node.GetBTreeCell(offsets[0]).Key.GetValues(); + Assert.Equal(1, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[1]).Key.GetValues(); + Assert.Equal(3, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[2]).Key.GetValues(); + Assert.Equal(5, tmpAtomList[0].IntegerValue); + tmpAtomList = node.GetBTreeCell(offsets[3]).Key.GetValues(); + Assert.Equal(6, tmpAtomList[0].IntegerValue); + + // delete by index 0 (cell with key == 1) + node.DeleteBTreeCell(node[0]); + tmpAtomList = node[0].Key.GetValues(); + Assert.Equal(3, tmpAtomList[0].IntegerValue); + tmpAtomList = node[1].Key.GetValues(); + Assert.Equal(5, tmpAtomList[0].IntegerValue); + tmpAtomList = node[2].Key.GetValues(); + Assert.Equal(6, tmpAtomList[0].IntegerValue); + + // delete remaining cells + node.DeleteBTreeCell(offsets[0]); + offsets = node.CellOffsetArray; + node.DeleteBTreeCell(offsets[0]); + offsets = node.CellOffsetArray; + node.DeleteBTreeCell(offsets[0]); + offsets = node.CellOffsetArray; + + pager.Close(); + } + + [Fact] + static void TestPagerSwapping() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 4); + + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + pager.ExtendNumberOfPages(); + // pager.ExtendNumberOfPages(); + + MemoryPage page1 = pager.ReadPage(1); + page1.IsPinned = true; + MemoryPage page2 = pager.ReadPage(2); + page2.Data[0] = 2; + MemoryPage page3 = pager.ReadPage(3); + MemoryPage page4 = pager.ReadPage(4); + MemoryPage page5 = pager.ReadPage(5); + Assert.False(page1.IsSwappedOut); + Assert.True(page2.IsSwappedOut); + Assert.False(page3.IsSwappedOut); + Assert.False(page4.IsSwappedOut); + Assert.False(page5.IsSwappedOut); + MemoryPage page6 = pager.ReadPage(6); + Assert.False(page1.IsSwappedOut); + Assert.True(page2.IsSwappedOut); + Assert.True(page3.IsSwappedOut); + Assert.False(page4.IsSwappedOut); + Assert.False(page5.IsSwappedOut); + Assert.False(page6.IsSwappedOut); + page4.Data[0] = 4; + page4[1] = 44; + MemoryPage page7 = pager.ReadPage(7); + Assert.False(page1.IsSwappedOut); + Assert.True(page2.IsSwappedOut); + Assert.True(page3.IsSwappedOut); + Assert.False(page4.IsSwappedOut); + Assert.True(page5.IsSwappedOut); + Assert.False(page6.IsSwappedOut); + Assert.False(page7.IsSwappedOut); + + // not enough pages + bool error = false; + try + { + MemoryPage page8 = pager.ReadPage(8); + } + catch (Exception) + { + error = true; + } + Assert.True(error); + + Assert.False(page1.IsSwappedOut); + Assert.Equal(page2.Data[0], 2); + Assert.Equal(page4.Data[0], 4); + Assert.Equal(page4[1], 44); + + pager.Close(); + } + + [Fact] + static void TestPager() + { + string dbPath = "./testdbfile.minidb"; + File.Delete(dbPath); + + Pager pager = new Pager(dbPath, 4096, 4); + + Assert.Equal(pager.PageCount, 1); + + pager.ExtendNumberOfPages(); + Assert.Equal(pager.PageCount, 2); + + MemoryPage page = pager.ReadPage(1); + page.Data[2] = 114; + page.Data[3] = 5; + page.Data[4] = 14; + + pager.WritePage(page); + MemoryPage page1 = pager.ReadPage(1); + + Assert.Equal(page.Data[2], page1.Data[2]); + Assert.Equal(page.Data[3], page1.Data[3]); + Assert.Equal(page.Data[4], page1.Data[4]); + + // it will save all dirty pages and remove all pages from recording + // after that, any MemoryPage returned from this `pager` will no longer legal to use + pager.Close(); + + pager.Open(dbPath); + // another page also with page number 1 + page1 = pager.ReadPage(1); + + // test if preventing buffer duplication + Assert.Equal(page.Data[2], page1.Data[2]); + Assert.Equal(page.Data[3], page1.Data[3]); + Assert.Equal(page.Data[4], page1.Data[4]); + + // test if the two page pointing to the same buffer + Assert.Equal(page1.Data[100], 0); + page.Data[100] = 1; + Assert.Equal(page1.Data[100], 1); + + pager.Close(); + } + + [Fact] + static void TestLeafIndexCell() + { + // init record + DBRecord record = GetTestBRecord(); + + // init key + List keyValues = new List(); + AtomValue key = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 8, StringValue = "114514" }; + keyValues.Add(key); + DBRecord keyRecord = new DBRecord(keyValues); + + // make raw bytes + List rawNode = new List(); + rawNode.AddRange(new byte[30]); + + // build cell + LeafIndexCell leafIndexCell = new LeafIndexCell(record, keyRecord); + byte[] raw = leafIndexCell.Pack(); + rawNode.AddRange(raw); + + // clone + LeafIndexCell clone = new LeafIndexCell(rawNode.ToArray(), 30); + + // assert + AssertCell(leafIndexCell, clone); + AssertDBRecords(leafIndexCell.PrimaryKey, clone.PrimaryKey); + } + + [Fact] + static void TestInternalIndexCell() + { + // init record + DBRecord record = GetTestBRecord(); + + // init key + List keyValues = new List(); + AtomValue key = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 8, StringValue = "114514" }; + keyValues.Add(key); + DBRecord keyRecord = new DBRecord(keyValues); + + // make raw bytes + List rawNode = new List(); + rawNode.AddRange(new byte[30]); + + // build cell + InternalIndexCell internalIndexCell = new InternalIndexCell(record, 114514, keyRecord); + byte[] raw = internalIndexCell.Pack(); + rawNode.AddRange(raw); + + // clone + InternalIndexCell clone = new InternalIndexCell(rawNode.ToArray(), 30); + + // assert + AssertCell(internalIndexCell, clone); + Assert.Equal(internalIndexCell.ChildPage, clone.ChildPage); + AssertDBRecords(internalIndexCell.PrimaryKey, clone.PrimaryKey); + } + + + [Fact] + static void TestInternalTableCell() + { + // init record + DBRecord record = GetTestBRecord(); + + // make raw bytes + List rawNode = new List(); + rawNode.AddRange(new byte[30]); + + // build cell + InternalTableCell internalTableCell = new InternalTableCell(record, 114514); + byte[] raw = internalTableCell.Pack(); + rawNode.AddRange(raw); + + // clone + InternalTableCell clone = new InternalTableCell(rawNode.ToArray(), 30); + + // assert + AssertCell(internalTableCell, clone); + Assert.Equal(internalTableCell.ChildPage, clone.ChildPage); + } + + [Fact] + static void TestLeafTableCell() + { + // init record + DBRecord record = GetTestBRecord(); + + // init key + List keyValues = new List(); + AtomValue key = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 8, StringValue = "114514" }; + keyValues.Add(key); + DBRecord keyRecord = new DBRecord(keyValues); + + // make raw bytes + List rawNode = new List(); + rawNode.AddRange(new byte[30]); + + // build cell + LeafTableCell leafTableCell = new LeafTableCell(keyRecord, record); + byte[] raw = leafTableCell.Pack(); + rawNode.AddRange(raw); + + // clone + LeafTableCell leafTableCellClone = new LeafTableCell(rawNode.ToArray(), 30); + + // assert + AssertDBRecords(leafTableCell.DBRecord, leafTableCellClone.DBRecord); + AssertCell(leafTableCell, leafTableCellClone); + } + + + + [Fact] + static void TestDBRecord() + { + // init record + List values = new List(); + AtomValue value1 = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = 222 }; + AtomValue value2 = new AtomValue() { Type = AttributeTypes.Null }; + AtomValue value3 = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 5, StringValue = "222" }; + values.Add(value1); + values.Add(value2); + values.Add(value3); + DBRecord record = new DBRecord(values); + + // make raw bytes + List rawNode = new List(); + rawNode.AddRange(new byte[30]); + + // clone + List valuesOut1 = record.GetValues(); + + // clone + byte[] raw = record.Pack(); + rawNode.AddRange(raw); + record.Unpack(rawNode.ToArray(), 30); + List valuesOut2 = record.GetValues(); + + int i; + for (i = 0; i < valuesOut2.Count; i++) + { + AssertAtomValue(values[i], valuesOut2[i]); + AssertAtomValue(valuesOut1[i], valuesOut2[i]); + } + } + + static DBRecord GetTestBRecord(int key = 222) + { + // init record + List values = new List(); + AtomValue value1 = new AtomValue() { Type = AttributeTypes.Int, IntegerValue = key }; + AtomValue value2 = new AtomValue() { Type = AttributeTypes.Null }; + AtomValue value3 = new AtomValue() { Type = AttributeTypes.Char, CharLimit = 5, StringValue = "222" }; + values.Add(value1); + values.Add(value2); + values.Add(value3); + DBRecord record = new DBRecord(values); + DBRecord cloneRecord = new DBRecord(record.Pack(), 0); + AssertDBRecords(record, cloneRecord); + return record; + } + + static void AssertCell(BTreeCell c1, BTreeCell c2) + { + Assert.Equal(c1.Types, c2.Types); + AssertDBRecords(c1.Key, c2.Key); + } + + static void AssertDBRecords(DBRecord r1, DBRecord r2) + { + List valuesOut1 = r1.GetValues(); + List valuesOut2 = r2.GetValues(); + + Assert.Equal(valuesOut1.Count, valuesOut2.Count); + + int i; + for (i = 0; i < valuesOut2.Count; i++) + { + AssertAtomValue(valuesOut1[i], valuesOut2[i]); + } + } + + static void AssertAtomValue(AtomValue v1, AtomValue v2) + { + Assert.Equal(v1.Type, v2.Type); + Assert.Equal(v1.CharLimit, v2.CharLimit); + Assert.Equal(v1.FloatValue, v2.FloatValue); + Assert.Equal(v1.IntegerValue, v2.IntegerValue); + Assert.Equal(v1.StringValue, v2.StringValue); + } + } +} diff --git a/tests/MiniSQL.Library.Tests/MiniSQL.Library.Tests.csproj b/tests/MiniSQL.Library.Tests/MiniSQL.Library.Tests.csproj new file mode 100644 index 0000000..45207e0 --- /dev/null +++ b/tests/MiniSQL.Library.Tests/MiniSQL.Library.Tests.csproj @@ -0,0 +1,23 @@ + + + + net5.0 + + false + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/tests/MiniSQL.Library.Tests/UnitTest1.cs b/tests/MiniSQL.Library.Tests/UnitTest1.cs new file mode 100644 index 0000000..aa7f0af --- /dev/null +++ b/tests/MiniSQL.Library.Tests/UnitTest1.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using MiniSQL.Library.Models; +using Xunit; + +namespace MiniSQL.Library.Tests +{ + public class UnitTest1 + { + [Fact] + static void MainEntry() + { + Console.WriteLine("[Library] Start test!"); + + TestExpression(); + + TestAtomValueOperators(); + + Console.WriteLine("[Library] End test!"); + } + + private static void TestAtomValueOperators() + { + AtomValue left = new AtomValue(); + AtomValue right = new AtomValue(); + left.StringValue = "abedeb"; + left.IntegerValue = 114; + left.FloatValue = 14.14; + right.StringValue = "abeceb"; + right.IntegerValue = 514; + right.FloatValue = 14.14; + + left.Type = AttributeTypes.Char; + right.Type = AttributeTypes.Char; + Assert.False((left < right).BooleanValue); + Assert.True((left> right).BooleanValue); + Assert.False((left == right).BooleanValue); + Assert.True((left != right).BooleanValue); + Assert.False((left <= right).BooleanValue); + Assert.True((left>= right).BooleanValue); + Assert.Equal("abedebabeceb", (left + right).StringValue); + + left.Type = AttributeTypes.Int; + right.Type = AttributeTypes.Int; + Assert.True((left < right).BooleanValue); + Assert.False((left> right).BooleanValue); + Assert.False((left == right).BooleanValue); + Assert.True((left != right).BooleanValue); + Assert.True((left <= right).BooleanValue); + Assert.False((left>= right).BooleanValue); + Assert.Equal(628, (left + right).IntegerValue); + Assert.Equal(-400, (left - right).IntegerValue); + Assert.Equal(114 * 514, (left * right).IntegerValue); + Assert.Equal(114 / 514, (left / right).IntegerValue); + + left.Type = AttributeTypes.Float; + right.Type = AttributeTypes.Float; + Assert.False((left < right).BooleanValue); + Assert.False((left> right).BooleanValue); + Assert.True((left == right).BooleanValue); + Assert.False((left != right).BooleanValue); + Assert.True((left <= right).BooleanValue); + Assert.True((left>= right).BooleanValue); + Assert.Equal(28.28, (left + right).FloatValue); + Assert.Equal(0.0, (left - right).FloatValue); + Assert.Equal(14.14 * 14.14, (left * right).FloatValue); + Assert.Equal(1, (left / right).FloatValue); + } + + private static void TestExpression() + { + TestAndList(); + TestCalculateSingleValue(); + TestFullCalculate(); + } + + private static void TestFullCalculate() + { + Expression exp = GetAndsExpression(); + + List nameValuePairs = new List(); + nameValuePairs.Add(new AttributeValue("a", new AtomValue { Type = AttributeTypes.Int, IntegerValue = 33 })); + nameValuePairs.Add(new AttributeValue("b", new AtomValue { Type = AttributeTypes.Char, CharLimit = 5, StringValue = "stc" })); + nameValuePairs.Add(new AttributeValue("c", new AtomValue { Type = AttributeTypes.Float, FloatValue = 6.0 })); + + AtomValue result = exp.Calculate(nameValuePairs); + Assert.True(result.BooleanValue); + + nameValuePairs[1].Value.StringValue = "stz"; + + result = exp.Calculate(nameValuePairs); + Assert.False(result.BooleanValue); + } + + private static void TestCalculateSingleValue() + { + Expression andsExpression = GetAndsExpression(); + string attributeName = "b"; + AtomValue attributeValue = new AtomValue(); + attributeValue.Type = AttributeTypes.Char; + attributeValue.CharLimit = 10; + attributeValue.StringValue = "aaa"; + Assert.True(andsExpression.CheckKey(attributeName, attributeValue)); + } + + private static void TestAndList() + { + Expression andsExpression = GetAndsExpression(); + var andList = andsExpression.SimpleMinterms; + // "not equal" operator is ignored + Assert.False(andList.ContainsKey("a")); + Assert.Equal(Operator.LessThanOrEqualTo, andList["b"].Operator); + Assert.Equal("str", andList["b"].RightOperand.ConcreteValue.StringValue); + Assert.Equal(Operator.LessThan, andList["c"].Operator); + Assert.Equal(6.6, andList["c"].RightOperand.ConcreteValue.FloatValue); + } + + private static Expression GetAndsExpression() + { + // __expression__ + // ((32 != a) and (b <= "str")) and (6.6> c) + // __tree structure__ + // and 1 + // and 2,> 3 + // != 4, <= 5, 6.6 6, c 7 + // 32 8, a 9, b 10, "str" 11 + + // 32 + Expression node8 = new Expression(); + node8.Operator = Operator.AtomConcreteValue; + node8.ConcreteValue = new AtomValue(); + node8.ConcreteValue.Type = AttributeTypes.Int; + node8.ConcreteValue.IntegerValue = 32; + // a + Expression node9 = new Expression(); + node9.Operator = Operator.AtomVariable; + node9.AttributeName = "a"; + // b + Expression node10 = new Expression(); + node10.Operator = Operator.AtomVariable; + node10.AttributeName = "b"; + // "str" + Expression node11 = new Expression(); + node11.Operator = Operator.AtomConcreteValue; + node11.ConcreteValue = new AtomValue(); + node11.ConcreteValue.Type = AttributeTypes.Char; + node11.ConcreteValue.CharLimit = 5; + node11.ConcreteValue.StringValue = "str"; + // != + Expression node4 = new Expression(); + node4.Operator = Operator.NotEqual; + node4.LeftOperand = node8; + node4.RightOperand = node9; + // <= + Expression node5 = new Expression(); + node5.Operator = Operator.LessThanOrEqualTo; + node5.LeftOperand = node10; + node5.RightOperand = node11; + // 6.6 + Expression node6 = new Expression(); + node6.Operator = Operator.AtomConcreteValue; + node6.ConcreteValue = new AtomValue(); + node6.ConcreteValue.Type = AttributeTypes.Float; + node6.ConcreteValue.FloatValue = 6.6; + // c + Expression node7 = new Expression(); + node7.Operator = Operator.AtomVariable; + node7.AttributeName = "c"; + // and + Expression node2 = new Expression(); + node2.Operator = Operator.And; + node2.LeftOperand = node4; + node2.RightOperand = node5; + //> + Expression node3 = new Expression(); + node3.Operator = Operator.MoreThan; + node3.LeftOperand = node6; + node3.RightOperand = node7; + // and + Expression node1 = new Expression(); + node1.Operator = Operator.And; + node1.LeftOperand = node2; + node1.RightOperand = node3; + + return node1; + } + } +}

AltStyle によって変換されたページ (->オリジナル) /