[
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\n[Xx]64/\n[Xx]86/\n[Bb]uild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n\n# TODO: Un-comment the next line if you do not want to checkin\n# your web deploy settings because they may include unencrypted\n# passwords\n#*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n# NuGet v3's project.json files produces more ignoreable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# LightSwitch generated files\nGeneratedArtifacts/\nModelManifest.xml\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n\n# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n## Build generated\nbuild/\nDerivedData/\n\n## Various settings\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata/\n\n## Other\n*.moved-aside\n*.xccheckout\n*.xcscmblueprint\n\n# SQLite\nsrc/sqlite3.c\nsrc/sqlite3.h\n\n# Catch\ncatch.hpp\n\n# Make Output\n*.db\n*.o\nsample/sample\ntest/test\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: cpp\nsudo: required\ncompiler:\n  - gcc\n  - clang\nscript:\n  - unzip -qu src/sqlite3.h.zip -d src\n  - unzip -qu src/sqlite3.c.zip -d src\n  - unzip -qu test/catch.hpp.zip -d test\n  - make -C sample && ./sample/sample\n  - make -C test && ./test/test\ninstall:\n  - if [ \"$CC\" = \"gcc\" ]; then export CXX=\"g++-5\" CC=\"gcc-5\"; fi\n  - if [ \"$CC\" = \"clang\" ]; then export CXX=\"clang++-3.8\" CC=\"clang-3.8\"; fi\naddons:\n  apt:\n    sources:\n    - ubuntu-toolchain-r-test\n    - llvm-toolchain-precise-3.8\n    packages:\n    - gcc-5\n    - g++-5\n    - clang-3.8\n    - unzip"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 BOT Man JL\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "﻿# ORM Lite\r\n\r\n**ORM Lite** is a C++ [_**Object Relation Mapping** (ORM)_](https://en.wikipedia.org/wiki/Object-relational_mapping)\r\nfor **SQLite3** (currently 😂),\r\nwritten in Modern C++ style.\r\n\r\n[![Build status - MSVC](https://ci.appveyor.com/api/projects/status/github/BOT-Man-JL/ORM-Lite?svg=true&branch=master)](https://ci.appveyor.com/project/BOT-Man-JL/ORM-Lite)\r\n[![Build status - gcc/clang](https://travis-ci.org/BOT-Man-JL/ORM-Lite.svg?branch=master)](https://travis-ci.org/BOT-Man-JL/ORM-Lite)\r\n\r\n## Features\r\n\r\n- **Easy** to Use\r\n- **Header Only**\r\n  ([src/ormlite.h](src/ormlite.h), [src/nullable.h](src/nullable.h))\r\n- **Powerful** Compile-time **Type/DSL Deduction**\r\n\r\n## Documentation\r\n\r\n#### [Get Started Here](docs/get-started.md) 😉\r\n\r\n#### [Full Document](docs/orm-lite.md) 😊\r\n\r\n## Planned Features\r\n\r\n- Support More Databases (Looking for a Better Driver recently...)\r\n- Customized Primary Key (Hard to Design an Elegant Interface for it...)\r\n- Blob (Hard to be Serialized to Script...)\r\n- Date/Time Types (Weak Typed in SQL...)\r\n- Subquery (Too Complicated... the Interface would be)\r\n\r\nFeel free to [Issue](https://github.com/BOT-Man-JL/ORM-Lite/issues/new),\r\nif you have any idea. 😎\r\n\r\n## Implementation Details （实现细节）\r\n\r\nPosts in **Chinese** only:\r\n\r\n- [How to Design a Naive C++ ORM](https://BOT-Man-JL.github.io/articles/?post=2016/How-to-Design-a-Naive-Cpp-ORM)\r\n- [How to Design a Better C++ ORM](https://bot-man-jl.github.io/articles/?post=2016/How-to-Design-a-Better-Cpp-ORM)\r\n"
  },
  {
    "path": "appveyor.yml",
    "content": "version: 1.0.{build}\r\nimage: Visual Studio 2017\r\nbuild_script:\r\n  - ps: Expand-Archive src/sqlite3.h.zip -DestinationPath src\r\n  - ps: Expand-Archive src/sqlite3.c.zip -DestinationPath src\r\n  - ps: Expand-Archive test/catch.hpp.zip -DestinationPath test\r\n  - ps: msbuild /verbosity:minimal sample/sample.vcxproj \"/p:Configuration=Debug;Platform=Win32\"\r\n  - ps: msbuild /verbosity:minimal sample/sample.vcxproj \"/p:Configuration=Debug;Platform=x64\"\r\n  - ps: msbuild /verbosity:minimal sample/sample.vcxproj \"/p:Configuration=Release;Platform=Win32\"\r\n  - ps: msbuild /verbosity:minimal sample/sample.vcxproj \"/p:Configuration=Release;Platform=x64\"\r\n  - ps: msbuild /verbosity:minimal test/test.vcxproj \"/p:Configuration=Debug;Platform=Win32\"\r\n  - ps: msbuild /verbosity:minimal test/test.vcxproj \"/p:Configuration=Debug;Platform=x64\"\r\n  - ps: msbuild /verbosity:minimal test/test.vcxproj \"/p:Configuration=Release;Platform=Win32\"\r\n  - ps: msbuild /verbosity:minimal test/test.vcxproj \"/p:Configuration=Release;Platform=x64\"\r\ntest_script:\r\n  - ps: sample\\Debug\\sample\\sample.exe\r\n  - ps: sample\\Release\\sample.exe\r\n  - ps: sample\\x64\\Debug\\sample\\sample.exe\r\n  - ps: sample\\x64\\Release\\sample.exe\r\n  - ps: test\\Debug\\test\\test.exe\r\n  - ps: test\\Release\\test.exe\r\n  - ps: test\\x64\\Debug\\test\\test.exe\r\n  - ps: test\\x64\\Release\\test.exe\r\n"
  },
  {
    "path": "docs/get-started.md",
    "content": "﻿# Get Started\r\n\r\nHere is a **short tour** for this **Amazing** ORM 😉\r\n\r\nThe full code is in [sample.cpp](../sample/sample.cpp).\r\n\r\n## Preparation\r\n\r\nBefore we start, Include **src** into your Project:\r\n\r\n- `ORMLite.h`\r\n- **SQLite3** Dependency\r\n\r\n> If you haven't installed **SQLite3**,\r\n> you can find the zip file of `sqlite3.h` and `sqlite3.c` in `/src`\r\n\r\n## Including *ORM Lite*\r\n\r\n``` cpp\r\n#include \"ORMLite.h\"\r\nusing namespace BOT_ORM;\r\nusing namespace BOT_ORM::Expression;\r\n\r\nstruct UserModel\r\n{\r\n    int user_id;\r\n    std::string user_name;\r\n    double credit_count;\r\n\r\n    Nullable<int> age;\r\n    Nullable<double> salary;\r\n    Nullable<std::string> title;\r\n\r\n    // Inject ORM-Lite into this Class :-)\r\n    ORMAP (\"UserModel\", user_id, user_name, credit_count,\r\n           age, salary, title);\r\n};\r\n```\r\n\r\n`Nullable<T>` helps us construct `Nullable` Value in C++,\r\nwhich is described in the [Document](orm-lite.md) 😁\r\n\r\nIn this sample, `ORMAP (\"UserModel\", ...)` do that:\r\n- `Class UserModel` will be mapped into `TABLE UserModel`;\r\n- NOT `Nullable` members will be mapped as `NOT NULL`;\r\n- `int, double, std::string` will be mapped into\r\n  `INT, REAL, TEXT` respectively;\r\n- The first entry `id` will be set as the **Primary Key** of the Table;\r\n\r\nAnd then we define and inject other 2 Classes in this sample:\r\n\r\n``` cpp\r\nstruct SellerModel\r\n{\r\n    int seller_id;\r\n    std::string seller_name;\r\n    double credit_count;\r\n\r\n    // Inject ORM-Lite into this Class :-)\r\n    ORMAP (\"SellerModel\", seller_id, seller_name, credit_count);\r\n};\r\n\r\nstruct OrderModel\r\n{\r\n    int order_id;\r\n    int user_id;\r\n    int seller_id;\r\n    std::string product_name;\r\n    Nullable<double> fee;\r\n\r\n    // Inject ORM-Lite into this Class :-)\r\n    ORMAP (\"OrderModel\", order_id, user_id, seller_id,\r\n           product_name, fee);\r\n};\r\n```\r\n\r\n## Field Extracting\r\n\r\n- `FieldExtractor`\r\n\r\n``` cpp\r\n// Define more Query Helper Objects and their Field Extractor\r\nUserModel user;\r\nSellerModel seller;\r\nOrderModel order;\r\nauto field = FieldExtractor { user, seller, order };\r\n\r\n// Extract Field from 'field'\r\n// For example: field (user.user_name)\r\n//   => Retrieve the field of user_name in UserModel table\r\n```\r\n\r\n## Working on *Database* with *ORMapper*\r\n\r\n- `ORMapper`\r\n\r\n``` cpp\r\n// Open a Connection with 'sample.db'\r\nORMapper mapper (\"sample.db\");\r\n```\r\n\r\n## Create or Drop Tables\r\n\r\n- `ORMapper.CreateTbl`\r\n- `ORMapper.DropTbl`\r\n- `Expression`\r\n\r\n``` cpp\r\n// Create Table with Constraints\r\nmapper.CreateTbl (\r\n    UserModel {},\r\n    Constraint::Default (field (user.salary), 1000.0));\r\n\r\n// Remarks:\r\n// CREATE TABLE UserModel(\r\n//   user_id INTEGER NOT NULL PRIMARY KEY,\r\n//   user_name TEXT NOT NULL,\r\n//   credit_count REAL NOT NULL,\r\n//   age INTEGER,\r\n//   salary REAL DEFAULT 1000,\r\n//   title TEXT);\r\n\r\nmapper.CreateTbl (\r\n    SellerModel {},\r\n    Constraint::Check (field (seller.credit_count) > 0.0));\r\n\r\n// Remarks:\r\n// CREATE TABLE SellerModel(\r\n//   seller_id INTEGER NOT NULL PRIMARY KEY,\r\n//   seller_name TEXT NOT NULL,\r\n//   credit_count REAL NOT NULL,\r\n//   CHECK (credit_count > 0));\r\n\r\nmapper.CreateTbl (\r\n    OrderModel {},\r\n    Constraint::Reference (\r\n        field (order.user_id), field (user.user_id)),\r\n    Constraint::Reference (\r\n        field (order.seller_id), field (seller.seller_id)),\r\n    Constraint::Unique (Constraint::CompositeField {\r\n        field (order.product_name), field (order.fee) }));\r\n\r\n// Remarks:\r\n// CREATE TABLE OrderModel(\r\n//   order_id INTEGER NOT NULL PRIMARY KEY,\r\n//   user_id INTEGER NOT NULL,\r\n//   seller_id INTEGER NOT NULL,\r\n//   product_name TEXT NOT NULL,\r\n//   fee REAL,\r\n//   FOREIGN KEY (user_id) REFERENCES UserModel(user_id),\r\n//   FOREIGN KEY (seller_id) REFERENCES SellerModel(seller_id),\r\n//   UNIQUE (product_name, fee));\r\n\r\n...\r\n\r\n// Drop Tables\r\nmapper.DropTbl (UserModel {});\r\nmapper.DropTbl (SellerModel {});\r\nmapper.DropTbl (OrderModel {});\r\n```\r\n\r\n#### User Model\r\n\r\n| user_id| user_name| credit_count|    age|  salary|  title|\r\n|--------|----------|-------------|-------|--------|-------|\r\n|       0|      John|          0.2|     21|  1000.0| `null`|\r\n|       1|      Jack|          0.4| `null`|    3.14| `null`|\r\n|       2|      Jess|          0.6| `null`|  1000.0|    Dr.|\r\n|     ...|       ...|          ...|    ...|     ...|    ...|\r\n\r\n#### Seller Model\r\n\r\n| seller_id| seller_name| credit_count|\r\n|----------|------------|-------------|\r\n|       ...|         ...|          ...|\r\n\r\n#### Order Model\r\n\r\n| order_id| user_id| seller_id| product_name| fee|\r\n|---------|--------|----------|-------------|----|\r\n|      ...|     ...|       ...|          ...| ...|\r\n\r\n## Basic CRUD\r\n\r\n- `ORMapper.Insert` (Create)\r\n- `ORMapper.Query`  (Read)\r\n- `ORMapper.Update` (Update)\r\n- `ORMapper.Delete` (Delete)\r\n- `ORMapper.Transaction`\r\n- `Table Constraints`\r\n\r\n``` cpp\r\nstd::vector<UserModel> initObjs =\r\n{\r\n    { 0, \"John\", 0.2, 21, nullptr, nullptr },\r\n    { 1, \"Jack\", 0.4, nullptr, 3.14, nullptr },\r\n    { 2, \"Jess\", 0.6, nullptr, nullptr, std::string (\"Dr.\") }\r\n};\r\n\r\n// Insert Values with Primary Key\r\nfor (const auto &obj : initObjs)\r\n    mapper.Insert (obj);\r\n\r\ninitObjs[1].salary = nullptr;\r\ninitObjs[1].title = \"St.\";\r\n\r\n// Update Entity by Primary Key (WHERE UserModel.id = 1)\r\nmapper.Update (initObjs[1]);\r\n\r\n// Delete Entity by Primary Key (WHERE UserModel.id = 2)\r\nmapper.Delete (initObjs[2]);\r\n\r\n// Transactional Statements\r\ntry\r\n{\r\n    mapper.Transaction ([&] ()\r\n    {\r\n        mapper.Delete (initObjs[0]);  // OK\r\n        mapper.Insert (UserModel {\r\n            1, \"Joke\", 0, nullptr, nullptr, nullptr\r\n        });  // Failed\r\n    });\r\n}\r\ncatch (const std::exception &ex)\r\n{\r\n    // If any statement Failed, throw an exception\r\n\r\n    std::cout << ex.what () << std::endl;\r\n    // SQL error: 'UNIQUE constraint failed: UserModel.id'\r\n\r\n    // Remarks:\r\n    // mapper.Delete (initObjs[0]); will not applied :-)\r\n}\r\n\r\n// Select All to List\r\nauto result1 = mapper.Query (UserModel {}).ToList ();\r\n\r\n// decltype (result1) == std::list<UserModel>\r\n// result1 = [{ 0, 0.2, \"John\", 21,   1000, null  },\r\n//            { 1, 0.4, \"Jack\", null, null, \"St.\" }]\r\n\r\n// Table Constraints\r\ntry\r\n{\r\n    // Insert Values without Primary Key\r\n    mapper.Insert (SellerModel { 0, \"John Inc.\", 0.0 }, false);\r\n}\r\ncatch (const std::exception &ex)\r\n{\r\n    std::cout << ex.what () << std::endl;\r\n    // SQL error: 'CHECK constraint failed: SellerModel'\r\n}\r\n```\r\n\r\n## Batch Operations\r\n\r\n- `ORMapper.InsertRange`\r\n- `ORMapper.UpdateRange`\r\n\r\n``` cpp\r\nstd::vector<UserModel> dataToSeed;\r\nfor (int i = 50; i < 100; i++)\r\n    dataToSeed.emplace_back (UserModel {\r\n        i, \"July_\" + std::to_string (i), i * 0.2,\r\n        nullptr, nullptr, nullptr\r\n});\r\n\r\n// Insert by Batch Insert\r\nmapper.Transaction ([&] () {\r\n    mapper.InsertRange (dataToSeed);\r\n});\r\n\r\nfor (size_t i = 0; i < 20; i++)\r\n{\r\n    dataToSeed[i + 30].age = 30 + (int) i / 2;\r\n    dataToSeed[i + 20].title = \"Mr. \" + std::to_string (i);\r\n}\r\n\r\n// Update by Batch Update\r\nmapper.Transaction ([&] () {\r\n    // Note that: it will erase the default value of 'salary'\r\n    mapper.UpdateRange (dataToSeed);\r\n});\r\n```\r\n\r\n## Single-Table Query\r\n\r\n- `Expression`\r\n- `Aggregate`\r\n- `Queryable.Where`\r\n- `Queryable.OrderBy`\r\n- `Queryable.Take`\r\n- `Queryable.Skip`\r\n- `Queryable.Select`\r\n\r\n``` cpp\r\n// Select by Condition\r\nauto result2 = mapper.Query (UserModel {})\r\n    .Where (\r\n        field (user.user_name) & std::string (\"July%\") &&\r\n        (field (user.age) >= 32 &&\r\n         field (user.title) != nullptr)\r\n    )\r\n    .OrderByDescending (field (user.age))\r\n    .OrderBy (field (user.user_id))\r\n    .Take (3)\r\n    .Skip (1)\r\n    .ToVector ();\r\n\r\n// Remarks:\r\n// SELECT * FROM UserModel\r\n// WHERE (user_name LIKE 'July%' AND\r\n//       (age >= 32 AND title IS NOT NULL))\r\n// ORDER BY age DESC, user_id\r\n// LIMIT 3 OFFSET 1\r\n\r\n// decltype (result2) == std::vector<UserModel>\r\n// result2 = [{ 89, 17.8, \"July_89\", 34, null, \"Mr. 19\" },\r\n//            { 86, 17.2, \"July_86\", 33, null, \"Mr. 16\" },\r\n//            { 87, 17.4, \"July_87\", 33, null, \"Mr. 17\" }]\r\n\r\n// Calculate Aggregate Function\r\nauto avg = mapper.Query (UserModel {})\r\n    .Where (field (user.user_name) & std::string (\"July%\"))\r\n    .Aggregate (Avg (field (user.credit_count)));\r\n\r\n// Remarks:\r\n// SELECT AVG (credit_count) FROM UserModel\r\n// WHERE (user_name LIKE 'July%')\r\n\r\n// avg = 14.9\r\n\r\nauto count = mapper.Query (UserModel {})\r\n    .Where (field (user.user_name) | std::string (\"July%\"))\r\n    .Aggregate (Count ());\r\n\r\n// Remarks:\r\n// SELECT COUNT (*) FROM UserModel\r\n// WHERE (user_name NOT LIKE 'July%')\r\n\r\n// count = 2\r\n```\r\n\r\n## Update / Delete by Statement\r\n\r\n- `Expression`\r\n- `ORMapper.Update`\r\n- `ORMapper.Delete`\r\n\r\n``` cpp\r\n// Update by Condition\r\nmapper.Update (\r\n    UserModel {},\r\n    (field (user.age) = 10) &&\r\n    (field (user.credit_count) = 1.0),\r\n    field (user.user_name) == std::string (\"July\"));\r\n\r\n// Remarks:\r\n// UPDATE UserModel SET age = 10,credit_count = 1.0\r\n// WHERE (user_name = 'July')\r\n\r\n// Delete by Condition\r\nmapper.Delete (UserModel {},\r\n               field (user.user_id) >= 90);\r\n\r\n// Remarks:\r\n// DELETE FROM UserModel WHERE (id >= 90)\r\n```\r\n\r\n## Multi-Table Query\r\n\r\n- `Expression`\r\n- `Aggregate`\r\n- `Queryable.Join`\r\n- `Queryable.LeftJoin`\r\n- `Queryable.Select`\r\n- `Queryable.GroupBy`\r\n- `Queryable.Having`\r\n- `Queryable.Union`\r\n\r\n``` cpp\r\nmapper.Transaction ([&] ()\r\n{\r\n    for (size_t i = 0; i < 50; i++)\r\n    {\r\n        mapper.Insert (\r\n            SellerModel { (int) i + 50,\r\n            \"Seller \" + std::to_string (i), 3.14 });\r\n        mapper.Insert (\r\n            OrderModel { 0,\r\n            (int) i / 2 + 50,\r\n            (int) i / 4 + 50,\r\n            \"Item \" + std::to_string (i),\r\n            i * 0.5 }, false);\r\n    }\r\n});\r\n\r\n// Join Tables for Query\r\nauto joinedQuery = mapper.Query (UserModel {})\r\n    .Join (OrderModel {},\r\n           field (user.user_id) ==\r\n           field (order.user_id))\r\n    .LeftJoin (SellerModel {},\r\n               field (seller.seller_id) ==\r\n               field (order.seller_id))\r\n    .Where (field (user.user_id) >= 65);\r\n\r\n// Get Result to List\r\nauto result3 = joinedQuery.ToList ();\r\n\r\n// Remarks:\r\n// SELECT * FROM UserModel\r\n//               JOIN OrderModel\r\n//               ON UserModel.user_id=OrderModel.user_id\r\n//               LEFT JOIN SellerModel\r\n//               ON SellerModel.seller_id=OrderModel.seller_id\r\n// WHERE (UserModel.user_id>=65)\r\n\r\n// decltype (result3) == std::list<std::tuple<Nullable<..>, ..>>\r\n// result3 = [(65, \"July_65\", 13, null, null, null,\r\n//             31, 65, 57, \"Item 30\", 15,\r\n//             57, \"Seller 7\", 3.14),\r\n//            (65, \"July_65\", 13, null, null, null,\r\n//             32, 65, 57, \"Item 31\", 15.5,\r\n//             57, \"Seller 7\", 3.14),\r\n//            ... ]\r\n\r\n// Group & Having ~\r\nauto result4 = joinedQuery\r\n    .Select (field (order.user_id),\r\n             field (user.user_name),\r\n             Avg (field (order.fee)))\r\n    .GroupBy (field (user.user_name))\r\n    .Having (Sum (field (order.fee)) >= 40.5)\r\n    .Skip (3)\r\n    .ToList ();\r\n\r\n// Remarks:\r\n// SELECT OrderModel.user_id,\r\n//        UserModel.user_name,\r\n//        AVG (OrderModel.fee)\r\n// FROM UserModel\r\n//      JOIN OrderModel\r\n//      ON UserModel.user_id=OrderModel.user_id\r\n//      LEFT JOIN SellerModel\r\n//      ON SellerModel.seller_id=OrderModel.seller_id\r\n// WHERE (UserModel.user_id>=65)\r\n// GROUP BY UserModel.user_name\r\n// HAVING SUM (OrderModel.fee)>=40.5\r\n// LIMIT ~0 OFFSET 3\r\n\r\n// decltype (result4) == std::list<std::tuple<Nullable<..>, ..>>\r\n// result4 = [(73, \"July_73\", 23.25),\r\n//            (74, \"July_74\", 24.25)]\r\n\r\n// Compound Select\r\n// Results are Nullable-Tuples\r\nauto result5 = mapper.Query (OrderModel {})\r\n    .Select (field (order.product_name), field (order.user_id))\r\n    .Where (field (order.user_id) == 50)\r\n    .Union (\r\n        joinedQuery\r\n        .Select (field (user.user_name), field (order.order_id))\r\n    )\r\n    .Take (4)\r\n    .ToList ();\r\n\r\n// Remarks:\r\n// SELECT OrderModel.product_name,\r\n//        OrderModel.user_id\r\n// FROM OrderModel\r\n//      WHERE (OrderModel.user_id==50)\r\n// UNION\r\n// SELECT UserModel.user_name,\r\n//        OrderModel.order_id\r\n// FROM UserModel\r\n//      JOIN OrderModel\r\n//      ON UserModel.user_id=OrderModel.user_id\r\n//      LEFT JOIN SellerModel\r\n//      ON SellerModel.seller_id=OrderModel.seller_id\r\n//      WHERE (UserModel.user_id>=65)\r\n// LIMIT 4;\r\n\r\n// decltype (result5) == std::list<std::tuple<Nullable<..>, ..>>\r\n// result5 = [(\"Item 0\", 50),\r\n//            (\"Item 1\", 50),\r\n//            (\"July_65\", 31),\r\n//            (\"July_65\", 32)]\r\n```\r\n\r\n## Wrapping Up\r\n\r\nThis little ORM is very cool, enjoy it. 😇\r\n\r\nSee the **[Full Document Here](orm-lite.md)**.\r\n"
  },
  {
    "path": "docs/orm-lite.md",
    "content": "﻿# ORM Lite\r\n\r\n## Requirements\r\n\r\n- **C++ 14** Support\r\n  - MSVC >= 14 (VS 2015 Update 3)\r\n  - gcc >= 5.4\r\n  - Clang >= 3.8\r\n- **SQLite 3** Dependency\r\n\r\n## Mapping\r\n\r\n|        SQL Concepts | C++ Concepts | Notes |\r\n|---------------------|--------------|-------|\r\n|    Table / Relation |       Object | Deduced by `ORMAP` |\r\n| Tuple (in `SELECT`) | `std::tuple` | Deduced by `Join` / `Select` |\r\n|              Column |        Field | Decuced by `Field` |\r\n\r\n## `BOT_ORM`\r\n\r\n``` cpp\r\n#include \"ORMLite.h\"\r\nusing namespace BOT_ORM;\r\nusing namespace BOT_ORM::Expression;\r\n```\r\n\r\nMacro `ORMAP` in `ORMLite.h`\r\n\r\n- `ORMAP (TableName, PrimaryKey, ...);`\r\n\r\nModules under `namespace BOT_ORM`\r\n\r\n- `BOT_ORM::Nullable`\r\n- `BOT_ORM::ORMapper`\r\n- `BOT_ORM::Queryable<QueryResult>`\r\n- `BOT_ORM::FieldExtractor`\r\n- `BOT_ORM::Constraint`\r\n\r\nModules under `namespace BOT_ORM::Expression`\r\n\r\n- `BOT_ORM::Expression::Selectable`\r\n- `BOT_ORM::Expression::Field`\r\n- `BOT_ORM::Expression::NullableField`\r\n- `BOT_ORM::Expression::Aggregate`\r\n- `BOT_ORM::Expression::Expr`\r\n- `BOT_ORM::Expression::SetExpr`\r\n- `BOT_ORM::Expression::Count ()`\r\n- `BOT_ORM::Expression::Sum ()`\r\n- `BOT_ORM::Expression::Avg ()`\r\n- `BOT_ORM::Expression::Max ()`\r\n- `BOT_ORM::Expression::Min ()`\r\n\r\nStatic Modules under `class BOT_ORM::Constraint`\r\n\r\n- `BOT_ORM::Constraint::CompositeField`\r\n- `BOT_ORM::Constraint::Default`\r\n- `BOT_ORM::Constraint::Check`\r\n- `BOT_ORM::Constraint::Unique`\r\n- `BOT_ORM::Constraint::Reference`\r\n\r\n## `ORMAP (TableName, PrimaryKey, ...)`\r\n\r\nBefore we use ORM Lite, we should **Inject** some code into the Class;\r\n\r\n``` cpp\r\nstruct MyClass\r\n{\r\n    int field1;\r\n    double field2;\r\n    std::string field3;\r\n\r\n    Nullable<int> field4;\r\n    Nullable<double> field5;\r\n    Nullable<std::string> field6;\r\n\r\n    // Inject ORM-Lite into this Class :-)\r\n    ORMAP (\"TableName\", field1, field2, field3,\r\n           field4, field5, field6);\r\n};\r\n```\r\n\r\nIn this sample, `ORMAP (\"TableName\", field1, ...)` specifies that:\r\n- Class `MyClass` will be mapped into Table `TableName`;\r\n- `field1, field2, field3, field4, field5, field6` will be mapped\r\n  into `INTEGER field1 NOT NULL`, `REAL field2 NOT NULL`,\r\n  `TEXT field3 NOT NULL`, `INTEGER field4`, `REAL field5`\r\n  and `TEXT field6` respectively;\r\n- The first entry `field1` will be set as the **Primary Key**\r\n  of the Table;\r\n\r\nNote that:\r\n- You should Pass **at least 2** Params into this Macro\r\n  (TableName and PrimaryKey), otherwise it will Not Compile...;\r\n- Currently Only Support\r\n  - T such that `std::is_integral<T>::value == true`\r\n    and **NOT** `char` or `*char_t`\r\n  - T such that `std::is_floating_point<T>::value == true`\r\n  - T such that `std::is_same<T, std::string>::value == true`\r\n  - which are mapped as `INTEGER`, `REAL` and `TEXT` (SQLite3);\r\n- Not `Nullable` members will be mapped as `NOT NULL`;\r\n- The **Primary Key** (first entry) is **Recommended** to be\r\n  `Integral`, and it could be regarded as the `ROWID`\r\n  with a Better Query **Performance** :-)\r\n  (otherwise SQLite 3 will Generate a Column for `ROWID` Implicitly)\r\n- Field Names MUST **NOT** be SQL Keywords (SQL Constraint);\r\n- `std::string` Value MUST **NOT** contain `\\0` (SQL Constraint);\r\n- `std::string` Value can be **utf-8** to support **Locale**;\r\n- `ORMAP (...)` will **auto** Inject some **private members**;\r\n  - `__Accept ()` to Implement **Visitor Pattern**;\r\n  - `__Tuple ()` to **Flatten** data to tuple;\r\n  - `__FieldNames ()` and `__TableName` to store strings;\r\n  - and the Access by Implementation;\r\n\r\n## `BOT_ORM::Nullable`\r\n\r\nIt keeps the *Similar Semantic* of `Nullable<T>` as `C#`; and\r\n[Reference Here](https://stackoverflow.com/questions/2537942/nullable-values-in-c/28811646#28811646)\r\n\r\n### Construction & Assignment\r\n\r\n- Default Constructed / `nullptr` Constructed / `nullptr` Assigned \r\n  object is `NULL` Valued;\r\n- Value Constructed / Value Assigned object is `NOT NULL` Valued\r\n- `Nullable` Objects are **Copyable** / **Movable**,\r\n  and the *Destination* Value has the *Same Value* as the *Source*\r\n\r\n``` cpp\r\n// Default or Null Construction\r\nNullable ();\r\nNullable (nullptr_t);\r\n\r\n// Null Assignment\r\nconst Nullable<T> & operator= (nullptr_t);\r\n\r\n// Value Construction\r\nNullable (const T &value);\r\n\r\n// Value Assignment\r\nconst Nullable<T> & operator= (const T &value);\r\n```\r\n\r\n### Get Value\r\n\r\nReturn the `Underlying Value` of the object or\r\n`Default Not-null Value` of `T`;\r\n(similar to `GetValueOrDefault` in C#)\r\n\r\n``` cpp\r\nconst T &Value (); const\r\n```\r\n\r\n### Comparison\r\n\r\nTwo Objects have the Same value only if their `Nullable` Construction:\r\n- Both are `NULL`;\r\n- Both are `NOT NULL` and have the Same `Underlying Value`;\r\n\r\n``` cpp\r\nbool operator==(const Nullable<T> &op1, const Nullable<T> &op2);\r\nbool operator==(const Nullable<T> &op1, T &op2);\r\nbool operator==(T &op1, const Nullable<T> &op2);\r\nbool operator==(const Nullable<T> &op1, nullptr_t);\r\nbool operator==(nullptr_t, const Nullable<T> &op2);\r\n```\r\n\r\n## `BOT_ORM::ORMapper`\r\n\r\n### Connection\r\n\r\n``` cpp\r\nORMapper (const string &connectionString);\r\n```\r\n\r\nRemarks:\r\n- Construct a **O/R Mapper** to connect to `connectionString`;\r\n- For SQLite, the `connectionString` is the **database name**;\r\n- The `ORMapper` **Keeps** the **Connection**\r\n  and **Shares** the **Connection** with `Queryable`;\r\n- **Disconnecting** at all related `ORMapper`/`Queryable` destructied;\r\n\r\n### Transaction\r\n\r\n``` cpp\r\nvoid Transaction (Fn fn);\r\n```\r\n\r\nRemarks:\r\n- Invoke `fn` **Transactionally**, as following:\r\n\r\n``` cpp\r\ntry\r\n{\r\n    _connector.Execute (\"begin transaction;\");\r\n    fn ();\r\n    _connector.Execute (\"commit transaction;\");\r\n}\r\ncatch (...)\r\n{\r\n    _connector.Execute (\"rollback transaction;\");\r\n    throw;\r\n}\r\n```\r\n\r\n### Create and Drop Table\r\n\r\n``` cpp\r\n// Create Table\r\nvoid CreateTbl (const MyClass &);\r\nvoid CreateTbl (const MyClass &,\r\n                const Constraint &constraint1,\r\n                const Constraint &constraint2,\r\n                ...);\r\n\r\n// Drop Table\r\nvoid DropTbl (const MyClass &);\r\n```\r\n\r\nRemarks:\r\n- Create/Drop Table for class `MyClass`;\r\n- `void CreateTbl (const MyClass &, ...);`\r\n  will Create a Table with **Constraints**;\r\n- `Constraint` will be described later;\r\n\r\nSQL:\r\n\r\n``` sql\r\nCREATE TABLE MyClass (...);\r\n\r\nDROP TABLE MyClass;\r\n```\r\n\r\n### Insert\r\n\r\n``` cpp\r\n// Insert a single value\r\nvoid Insert (const MyClass &entity, bool withId = true);\r\n\r\n// Insert values\r\nvoid InsertRange (const Container<MyClass> &entities, bool withId = true);\r\n```\r\n\r\nRemarks:\r\n- Insert `entity` / `entities` into Table for `MyClass`;\r\n- If `withId` is `false`, it will insert the `entity`\r\n  without **Primary Key**;\r\n  - Note that: **Primary Key** is recommended to be **Integral**\r\n    in this case (**INT PK** would be `AUTOINCREMENT`,\r\n    Floating Point / String may **Failed**);\r\n- **NULL** Fields will **NOT** be Set;\r\n- `entities` must **SUPPORT** `forward_iterator`;\r\n\r\nSQL:\r\n\r\n``` sql\r\nINSERT INTO MyClass (...) VALUES (...);\r\n\r\nINSERT INTO MyClass (...) VALUES (...);\r\nINSERT INTO MyClass (...) VALUES (...);\r\n...\r\n```\r\n\r\n### Update\r\n\r\n``` cpp\r\n// Update value by Primary Key\r\nvoid Update (const MyClass &entity);\r\n\r\n// Update values by Primary Key\r\nvoid UpdateRange (const Container<MyClass> &entities);\r\n\r\n// Update by Expressions\r\nvoid Update (const MyClass &,\r\n             const Expression::SetExpr &setExpr,\r\n             const Expression::Expr &whereExpr);\r\n```\r\n\r\nRemarks:\r\n- Update `entity` / `entities` in Table `MyClass`\r\n  with the Same **Primary Key**;\r\n- Update Set `setExpr` Where `whereExpr` for Table `MyClass`\r\n  (`Expressions` will be described later);\r\n- **NULL** Fields will also be Set;\r\n- `entities` must **SUPPORT** `forward_iterator`;\r\n\r\nSQL:\r\n\r\n``` sql\r\nUPDATE MyClass SET (...) WHERE KEY = <entity.id>;\r\n\r\nUPDATE MyClass SET (...) WHERE KEY = <entity.id>;\r\nUPDATE MyClass SET (...) WHERE KEY = <entity.id>;\r\n...\r\n\r\nUPDATE MyClass SET (...) WHERE ...;\r\n```\r\n\r\n### Delete\r\n\r\n``` cpp\r\n// Delete value by Primary Key\r\nvoid Delete (const MyClass &entity);\r\n\r\n// Delete by Expressions\r\nvoid Delete (const MyClass &,\r\n             const Expression::Expr &whereExpr);\r\n```\r\n\r\nRemarks:\r\n- Delete Entry in Table `MyClass` with the Same **Primary Key**;\r\n- Delete Where `whereExpr` for Table `MyClass`\r\n  (`Expression` will be described later);\r\n- This function will **NOT** throw a `std::runtime_error`\r\n  even if there is nothing to delete;\r\n\r\nSQL:\r\n\r\n``` sql\r\nDELETE FROM MyClass WHERE KEY = <entity.id>;\r\n\r\nDELETE FROM MyClass WHERE ...;\r\n```\r\n\r\n### Query\r\n\r\n``` cpp\r\n// Retrieve a Queryable Object\r\nQueryable<MyClass> Query (MyClass queryHelper);\r\n```\r\n\r\nRemarks:\r\n- Return new `Queryable` object with `QueryResult` is `MyClass`;\r\n- `MyClass` **MUST** be **Copy Constructible**\r\n  to Construct a `queryHelper`;\r\n- The `ORMapper` **Shares** the **Connection** with `Queryable`;\r\n\r\n## `BOT_ORM::Queryable<QueryResult>`\r\n\r\n### Retrieve Results\r\n\r\n``` cpp\r\nNullable<T> Aggregate (const Expression::Aggregate<T> &agg) const;\r\nstd::vector<QueryResult> ToVector () const;\r\nstd::list<QueryResult> ToList () const;\r\n```\r\n\r\nRemarks:\r\n- `QueryResult` specifies the **Row Type** of Query Result;\r\n- `Aggregate` will Get the one-or-zero-row Result for `agg`;\r\n- `ToVector` / `ToList` returns the Collection of `QueryResult`;\r\n- The results are from the **Connection** of `Queryable`;\r\n- If the Result is `null` for `NOT Nullable` Field,\r\n  it will throw `std::runtime_error`;\r\n- `Expression` will be described later;\r\n\r\n### Set Conditions\r\n\r\n``` cpp\r\nQueryable Distinct (bool isDistinct = true) const;\r\nQueryable Where (const Expression::Expr &expr) const;\r\n\r\nQueryable GroupBy (const Expression::Field<T> &field) const;\r\nQueryable Having (const Expression::Expr &expr) const;\r\n\r\nQueryable OrderBy (const Expression::Field<T> &field) const;\r\nQueryable OrderByDescending (const Expression::Field<T> &field) const;\r\n\r\nQueryable Take (size_t count) const;\r\nQueryable Skip (size_t count) const;\r\n```\r\n\r\nRemarks:\r\n- Default Selection is `ALL`;\r\n- These functions will Set/Append Conditions to a copy of `this`;\r\n- `OrderBy` will **Append** `field` to Condition,\r\n  while Other functions will **Set** `DISTINCT`,\r\n  `expr`, `field` or `count` to Condition;\r\n- New `Queryable` **Shares** the **Connection** of `this`;\r\n- `Expression` will be described later;\r\n\r\n### Construct New `QueryResult`\r\n\r\n``` cpp\r\nauto Select (const Expression::Selectable<T1> &target1,\r\n             const Expression::Selectable<T2> &target2,\r\n             ...) const;\r\nauto Join (const MyClass2 &queryHelper2,\r\n           const Expression::Expr &onExpr) const;\r\nauto LeftJoin (const MyClass2 &queryHelper2,\r\n               const Expression::Expr &onExpr) const;\r\n```\r\n\r\nRemarks:\r\n- Default Selection is **All Columns** (`SELECT *`);\r\n- `Select` will Set `QueryResult` to `std::tuple<T1, T2, ...>`,\r\n  which can be retrieved by `SELECT target1, target2, ...`\r\n  (`target` can be **Field** or **Aggregate Functions**);\r\n- `Join` / `LeftJoin` will Set `QueryResult` to `std::tuple<...>`\r\n  - `...` is the **flattened nullable concatenation** of all entries of\r\n    **Previous** `QueryResult` and `queryHelper2`;\r\n  - **Flatten** and **Nullable** means all fields of `...` are\r\n    all `Nullable<T>`, where `T` is the Supported Types of `ORMAP`\r\n    (NOT `std::tuple` or `MyClass`);\r\n  - `onExpr` specifies the `ON` Expression for `JOIN`;\r\n- All Functions will copy the **Conditions** of `this` to the new one;\r\n- New `Queryable` **Shares** the **Connection** of `this`;\r\n- `Expression` will be described later;\r\n\r\n### Compound Select\r\n\r\n``` cpp\r\nQueryable Union (const Queryable &queryable) const;\r\nQueryable UnionAll (const Queryable &queryable) const;\r\nQueryable Intersect (const Queryable &queryable) const;\r\nQueryable Expect (const Queryable &queryable) const;\r\n```\r\n\r\nRemarks:\r\n- All Functions will return a Compound Select\r\n  for `this` and `queryable`;\r\n- All Functions will only **Inherit Conditions**\r\n  `OrderBy` and `Limit` from `this`;\r\n- New `Queryable` **Shares** the **Connection** of `this`;\r\n\r\n### Query SQL\r\n\r\nWe will use the following SQL to Query:\r\n\r\n``` sql\r\nSELECT [DISTINCT] ...\r\nFROM TABLE\r\n     [LEFT] JOIN TABLE ON ...\r\n     ...\r\nWHERE ...\r\nGROUP BY <field>\r\nHAVING ...\r\n[<Compound> SELECT ... FROM ...]\r\nORDER BY <field> [DESC], ...\r\nLIMIT <take> OFFSET <skip>;\r\n```\r\n\r\nRemarks:\r\n- If the Corresponding Condition is NOT Set, it will be omitted;\r\n\r\n## `BOT_ORM::FieldExtractor`\r\n\r\n``` cpp\r\n// Construction\r\nFieldExtractor (const MyClass1 &queryHelper1,\r\n                const MyClass2 &queryHelper2,\r\n                ...);\r\n\r\n// Get Field<> by operator ()\r\nField<T> operator () (const T &field) const;\r\nNullableField<T> operator () (const Nullable<T> &field) const;\r\n```\r\n\r\nRemarks:\r\n- Construction of `FieldExtractor` will take all fields' pointers of\r\n  `queryHelper` into a **Hash Table**;\r\n- `operator () (field)` will find the position of `field`\r\n  in the **Hash Table** from `queryHelper`\r\n  and Construct the corresponding `Field`;\r\n- If the `field` is `Nullable<T>`\r\n  it will Construct a `NullableField<T>`;\r\n  and it will Construct a `Field<T>` otherwise;\r\n- If `field` is not a member of `queryHelper`,\r\n  it will throw `std::runtime_error`;\r\n- `Expression` will be described later;\r\n\r\n## `namespace BOT_ORM::Expression`\r\n\r\n### Fields and Aggregate Functions\r\n\r\n#### Definitions\r\n\r\n``` cpp\r\nBOT_ORM::Expression::Selectable<T>\r\nBOT_ORM::Expression::Field<T> : public Selectable<T>\r\nBOT_ORM::Expression::NullableField<T> : public Field<T>\r\nBOT_ORM::Expression::Aggregate<T> : public Selectable<T>\r\n```\r\n\r\n#### Operations\r\n\r\n``` cpp\r\n// Field / Aggregate ? Value\r\nExpr operator == (const Selectable<T> &op, T value);\r\nExpr operator != (const Selectable<T> &op, T value);\r\nExpr operator >  (const Selectable<T> &op, T value);\r\nExpr operator >= (const Selectable<T> &op, T value);\r\nExpr operator <  (const Selectable<T> &op, T value);\r\nExpr operator <= (const Selectable<T> &op, T value);\r\n\r\n// Field ? Field\r\nExpr operator == (const Field<T> &op1, const Field<T> &op2);\r\nExpr operator != (const Field<T> &op1, const Field<T> &op2);\r\nExpr operator >  (const Field<T> &op1, const Field<T> &op2);\r\nExpr operator >= (const Field<T> &op1, const Field<T> &op2);\r\nExpr operator <  (const Field<T> &op1, const Field<T> &op2);\r\nExpr operator <= (const Field<T> &op1, const Field<T> &op2);\r\n\r\n// Nullable Field ? nullptr\r\nExpr operator == (const NullableField<T> &op, nullptr_t);\r\nExpr operator !== (const NullableField<T> &op, nullptr_t);\r\n\r\n// String Field ? std::string\r\nExpr operator& (const Field<std::string> &op, std::string val);\r\nExpr operator| (const Field<std::string> &op, std::string val);\r\n\r\n// Get SetExpr\r\nSetExpr operator = (const Field<T> &op, T value);\r\nSetExpr operator = (const NullableField<T> &op, nullptr_t);\r\n```\r\n\r\nRemarks:\r\n- `Selectable<T> ? T` returns `Expr<op ? value>`;\r\n- `Field<T> ? Field<T>` returns `Expr<op1 ? op2>`;\r\n- `NullableField<T> == / != nullptr`\r\n  returns `Expr<op> IS NULL / IS NOT NULL`;\r\n- `Field<std::string> & / | T`\r\n  returns `Expr<op> LIKE / NOT LIKE <value>`;\r\n- `Field<T> = T` returns `SetExpr<op> = <value>`;\r\n- `NullableField<T> = nullptr` returns `SetExpr<op> = null`;\r\n\r\n### Expressions\r\n\r\n#### Definitions\r\n\r\n``` cpp\r\nBOT_ORM::Expression::Expr\r\nBOT_ORM::Expression::SetExpr\r\n```\r\n\r\n#### Operations\r\n\r\n``` cpp\r\n// Get Composite Expr\r\nExpr operator && (const Expr &op1, const Expr &op2);\r\nExpr operator || (const Expr &op1, const Expr &op2);\r\n\r\n// Concatenate 2 SetExpr\r\nSetExpr operator && (const SetExpr &op1, const SetExpr &op2);\r\n```\r\n\r\nRemarks:\r\n- `Expr && / || Expr` returns `(<op1> and / or <op2>)`;\r\n- `SetExpr && SetExpr` returns `<op1>, <op2>`;\r\n\r\n### Aggregate Function Helpers\r\n\r\n``` cpp\r\nBOT_ORM::Expression::Count ();\r\nBOT_ORM::Expression::Count (const Field<T> &field);\r\nBOT_ORM::Expression::Sum (const Field<T> &field);\r\nBOT_ORM::Expression::Avg (const Field<T> &field);\r\nBOT_ORM::Expression::Max (const Field<T> &field);\r\nBOT_ORM::Expression::Min (const Field<T> &field);\r\n```\r\n\r\nRemarks:\r\n\r\nThey will Generate Aggregate Functions as:\r\n\r\n- `size_t COUNT (*)`\r\n- `size_t COUNT (field)`\r\n- `T SUM (field)`\r\n- `T AVG (field)`\r\n- `T MAX (field)`\r\n- `T MIN (field)`\r\n\r\n## `class BOT_ORM::Constraint`\r\n\r\n### Composite Field\r\n\r\n`CompositeField` could be constructed from normal `Field`\r\nand is used by **Constraint Functions**;\r\n\r\n``` cpp\r\nCompositeField (const Expression::Field<T1> &field1,\r\n                const Expression::Field<T2> &field2,\r\n                ...);\r\n```\r\n\r\nRemarks:\r\n- Composite Field will Contain fields in the given **Order**;\r\n- If the `field`s are not from the Same Table,\r\n  it will throw `std::runtime_error`;\r\n\r\n### Generate Constraints\r\n\r\n``` cpp\r\nConstraint Default (const Expression::Field<T> &field,\r\n                    const T &value);\r\nConstraint Check (const Expression::Expr &expr);\r\nConstraint Unique (const Expression::Field<T> &field);\r\nConstraint Unique (const CompositeField &fields);\r\nConstraint Reference(const Expression::Field<T> &field,\r\n                     const Expression::Field<T> &refered);\r\nConstraint Reference (const CompositeField &field,\r\n                      const CompositeField &refered);\r\n```\r\n\r\nRemarks:\r\n- They will Generate Constraints as:\r\n  `DEFAULT`, `CHECK`, `UNIQUE` and `FOREIGN KEY`;\r\n- `FOREIGN KEY` is Enabled by Default\r\n  (during the Construction of `ORMapper`);\r\n- Why there is NO **Composite Primary Key** Constaints:\r\n  - It's recommended to use a **Integral** Field as the Primary Key,\r\n    described in Section ## Macro `ORMAP`;\r\n  - We can use `Unique` to implement a **Composite Unique** Constraint;\r\n  - And use `Reference` to define a **Composite Foreign Key**;\r\n\r\n## Error Handling\r\n\r\n### Compile-time Error\r\n\r\nORM Lite uses `static_assert` to Check if the Code is valid:\r\n\r\n- **Forget** to **Place** `ORMAP` into the Class\r\n  > Please Inject the Class with 'ORMAP' first\r\n- Place **Unsupported Types** into `ORMAP`\r\n  > Only Support Integral, Floating Point and std::string\r\n\r\nNote that: Error Messages will often appear at the **TOP**;\r\n\r\n### Runtime Error\r\n\r\nAll Functions will throw `std::runtime_error`\r\nwith the **Error Message** if Failed:\r\n\r\n- Failed to **Connect** to **Database**\r\n  > SQL error: Can't open database `<connectionString>`\r\n- Failed at Executing **Query** Script\r\n  > SQL error: `<ErrorMessage>` at `<Generated SQL Script>`\r\n- Query Result's **Column Count** does **NOT Match** the Expected Count\r\n  (happening in **NOT** *Code First* Cases...)\r\n  > SQL error: Bad Column Count at `<Generated SQL Script>`\r\n- Get `NULL` from Query while the Expected **Field** is **NOT NULL**\r\n  (happening in **NOT** *Code First* Cases...)\r\n  > SQL error: Get Null Value at `<Generated SQL Script>`\r\n- Pass a **Non-Member** Var of Registered Object to Field **Extractor**\r\n  > No Such Field for current Extractor\r\n- **Composite** Fields from **NOT** the Same Tables\r\n  > Fields are NOT from the Same Table"
  },
  {
    "path": "sample/makefile",
    "content": "\nTARGET = sample\nSOURCES = sample.cpp ../src/sqlite3.c\nWARNINGFLAGS = -Wall -W\nCPPFLAGS = -std=c++14\nLINKS = -lstdc++ -lpthread -ldl\n\nOBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))\n\n%.o: %.c\n\t$(CC) -c $< -o $@ $(WARNINGFLAGS) $(LINKS)\n\n%.o: %.cpp\n\t$(CC) -c $< -o $@ $(WARNINGFLAGS) $(LINKS) $(CPPFLAGS)\n\n$(TARGET): $(OBJS)\n\t$(CC) $(OBJS) -o $(TARGET) $(LINKS)\n\nclean:\n\trm -rf $(OBJS) $(TARGET) *.db\n"
  },
  {
    "path": "sample/sample.cpp",
    "content": "\n// Sample of ORM Lite\n// https://github.com/BOT-Man-JL/ORM-Lite\n// BOT Man, 2016\n\n#include <string>\n#include <iostream>\n#include <tuple>\n\n#include \"../src/ormlite.h\"\nusing namespace BOT_ORM;\nusing namespace BOT_ORM::Expression;\n\nnamespace PrintHelper\n{\n    template<class T>\n    void PrintNullable (const BOT_ORM::Nullable<T> &val)\n    {\n        if (val == nullptr)\n            std::cout << \"null\";\n        else\n            std::cout << val.Value ();\n    }\n\n    template<class Tuple, std::size_t N>\n    struct TuplePrinter\n    {\n        static void print (const Tuple& t)\n        {\n            TuplePrinter<Tuple, N - 1>::print (t);\n            std::cout << \", \";\n            PrintNullable (std::get<N - 1> (t));\n        }\n    };\n\n    template<class Tuple>\n    struct TuplePrinter<Tuple, 1>\n    {\n        static void print (const Tuple& t)\n        {\n            PrintNullable (std::get<0> (t));\n        }\n    };\n\n    template<class... Args>\n    void PrintTuple (const std::tuple<Args...>& t)\n    {\n        std::cout << \"(\";\n        TuplePrinter<decltype(t), sizeof...(Args)>::print (t);\n        std::cout << \")\\n\";\n    }\n\n    template<class Container>\n    void PrintTuples (const Container &vals)\n    {\n        for (const auto &val : vals)\n            PrintTuple (val);\n        std::cout << std::endl;\n    }\n}\n\nstruct UserModel\n{\n    int user_id;\n    std::string user_name;\n    double credit_count;\n\n    Nullable<int> age;\n    Nullable<double> salary;\n    Nullable<std::string> title;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"UserModel\", user_id, user_name, credit_count, age, salary, title);\n};\n\nstruct SellerModel\n{\n    int seller_id;\n    std::string seller_name;\n    double credit_count;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"SellerModel\", seller_id, seller_name, credit_count);\n};\n\nstruct OrderModel\n{\n    int order_id;\n    int user_id;\n    int seller_id;\n    std::string product_name;\n    Nullable<double> fee;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"OrderModel\", order_id, user_id, seller_id, product_name, fee);\n};\n\nint main ()\n{\n    /*\n        ## Field Extracting\n    */\n\n    // Define more Query Helper Objects and their Field Extractor\n    UserModel user;\n    SellerModel seller;\n    OrderModel order;\n    auto field = FieldExtractor { user, seller, order };\n\n    // Extract Field from 'field'\n    // For example: field (user.user_name)\n    //   => Retrieve the field of user_name in UserModel table\n\n    /*\n        ## Working on *Database* with *ORMapper*\n    */\n\n    // Open a Connection with 'sample.db'\n    ORMapper mapper (\"sample.db\");\n\n    /*\n        ## Create or Drop Tables\n    */\n\n    try\n    {\n        // Drop Tables\n        mapper.DropTbl (OrderModel {});\n        mapper.DropTbl (UserModel {});\n        mapper.DropTbl (SellerModel {});\n    }\n    catch (...) {}\n\n    // Create Table with Constraints\n    mapper.CreateTbl (\n        UserModel {},\n        Constraint::Default (field (user.salary), 1000.0));\n\n    // Remarks:\n    // CREATE TABLE UserModel(\n    //   user_id INTEGER NOT NULL PRIMARY KEY,\n    //   user_name TEXT NOT NULL,\n    //   credit_count REAL NOT NULL,\n    //   age INTEGER,\n    //   salary REAL DEFAULT 1000,\n    //   title TEXT);\n\n    mapper.CreateTbl (\n        SellerModel {},\n        Constraint::Check (field (seller.credit_count) > 0.0));\n\n    // Remarks:\n    // CREATE TABLE SellerModel(\n    //   seller_id INTEGER NOT NULL PRIMARY KEY,\n    //   seller_name TEXT NOT NULL,\n    //   credit_count REAL NOT NULL,\n    //   CHECK (credit_count > 0));\n\n    mapper.CreateTbl (\n        OrderModel {},\n        Constraint::Reference (\n            field (order.user_id), field (user.user_id)),\n        Constraint::Reference (\n            field (order.seller_id), field (seller.seller_id)),\n        Constraint::Unique (Constraint::CompositeField {\n            field (order.product_name), field (order.fee) }));\n\n    // Remarks:\n    // CREATE TABLE OrderModel(\n    //   order_id INTEGER NOT NULL PRIMARY KEY,\n    //   user_id INTEGER NOT NULL,\n    //   seller_id INTEGER NOT NULL,\n    //   product_name TEXT NOT NULL,\n    //   fee REAL,\n    //   FOREIGN KEY (user_id) REFERENCES UserModel(user_id),\n    //   FOREIGN KEY (seller_id) REFERENCES SellerModel(seller_id),\n    //   UNIQUE (product_name, fee));\n\n    /*\n        ## Basic CRUD\n    */\n\n    std::vector<UserModel> initObjs =\n    {\n        { 0, \"John\", 0.2, 21, nullptr, nullptr },\n        { 1, \"Jack\", 0.4, nullptr, 3.14, nullptr },\n        { 2, \"Jess\", 0.6, nullptr, nullptr, std::string (\"Dr.\") }\n    };\n\n    // Insert Values with Primary Key\n    for (const auto &obj : initObjs)\n        mapper.Insert (obj);\n\n    initObjs[1].salary = nullptr;\n    initObjs[1].title = \"St.\";\n\n    // Update Entity by Primary Key (WHERE UserModel.id = 1)\n    mapper.Update (initObjs[1]);\n\n    // Delete Entity by Primary Key (WHERE UserModel.id = 2)\n    mapper.Delete (initObjs[2]);\n\n    // Transactional Statements\n    try\n    {\n        mapper.Transaction ([&] ()\n        {\n            mapper.Delete (initObjs[0]);  // OK\n            mapper.Insert (UserModel {\n                1, \"Joke\", 0, nullptr, nullptr, nullptr\n            });  // Failed\n        });\n    }\n    catch (const std::exception &ex)\n    {\n        // If any statement Failed, throw an exception\n\n        std::cout << ex.what () << std::endl;\n        // SQL error: 'UNIQUE constraint failed: UserModel.id'\n\n        // Remarks:\n        // mapper.Delete (initObjs[0]); will not applied :-)\n    }\n\n    // Select All to List\n    auto result1 = mapper.Query (UserModel {}).ToList ();\n\n    // decltype (result1) == std::list<UserModel>\n    // result1 = [{ 0, 0.2, \"John\", 21,   1000, null  },\n    //            { 1, 0.4, \"Jack\", null, null, \"St.\" }]\n\n    // Table Constraints\n    try\n    {\n        // Insert Values without Primary Key\n        mapper.Insert (SellerModel { 0, \"John Inc.\", 0.0 }, false);\n    }\n    catch (const std::exception &ex)\n    {\n        std::cout << ex.what () << std::endl;\n        // SQL error: 'CHECK constraint failed: SellerModel'\n    }\n\n    /*\n        ## Batch Operations\n    */\n\n    std::vector<UserModel> dataToSeed;\n    for (int i = 50; i < 100; i++)\n        dataToSeed.emplace_back (UserModel {\n            i, \"July_\" + std::to_string (i), i * 0.2,\n            nullptr, nullptr, nullptr\n    });\n\n    // Insert by Batch Insert\n    mapper.Transaction ([&] () {\n        mapper.InsertRange (dataToSeed);\n    });\n\n    for (size_t i = 0; i < 20; i++)\n    {\n        dataToSeed[i + 30].age = 30 + (int) i / 2;\n        dataToSeed[i + 20].title = \"Mr. \" + std::to_string (i);\n    }\n\n    // Update by Batch Update\n    mapper.Transaction ([&] () {\n        // Note that: it will erase the default value of 'salary'\n        mapper.UpdateRange (dataToSeed);\n    });\n\n    /*\n        ## Single-Table Query\n    */\n\n    // Select by Condition\n    auto result2 = mapper.Query (UserModel {})\n        .Where (\n            field (user.user_name) & std::string (\"July%\") &&\n            (field (user.age) >= 32 &&\n                field (user.title) != nullptr)\n        )\n        .OrderByDescending (field (user.age))\n        .OrderBy (field (user.user_id))\n        .Take (3)\n        .Skip (1)\n        .ToVector ();\n\n    // Remarks:\n    // SELECT * FROM UserModel\n    // WHERE (user_name LIKE 'July%' AND\n    //       (age >= 32 AND title IS NOT NULL))\n    // ORDER BY age DESC, user_id\n    // LIMIT 3 OFFSET 1\n\n    // decltype (result2) == std::vector<UserModel>\n    // result2 = [{ 89, 17.8, \"July_89\", 34, null, \"Mr. 19\" },\n    //            { 86, 17.2, \"July_86\", 33, null, \"Mr. 16\" },\n    //            { 87, 17.4, \"July_87\", 33, null, \"Mr. 17\" }]\n\n    // Calculate Aggregate Function\n    auto avg = mapper.Query (UserModel {})\n        .Where (field (user.user_name) & std::string (\"July%\"))\n        .Aggregate (Avg (field (user.credit_count)));\n\n    // Remarks:\n    // SELECT AVG (credit_count) FROM UserModel\n    // WHERE (user_name LIKE 'July%')\n\n    // avg = 14.9\n\n    auto count = mapper.Query (UserModel {})\n        .Where (field (user.user_name) | std::string (\"July%\"))\n        .Aggregate (Count ());\n\n    // Remarks:\n    // SELECT COUNT (*) FROM UserModel\n    // WHERE (user_name NOT LIKE 'July%')\n\n    // count = 2\n\n    /*\n        ## Update / Delete by Statement\n    */\n\n    // Update by Condition\n    mapper.Update (\n        UserModel {},\n        (field (user.age) = 10) &&\n        (field (user.credit_count) = 1.0),\n        field (user.user_name) == std::string (\"July\"));\n\n    // Remarks:\n    // UPDATE UserModel SET age = 10,credit_count = 1.0\n    // WHERE (user_name = 'July')\n\n    // Delete by Condition\n    mapper.Delete (UserModel {},\n        field (user.user_id) >= 90);\n\n    // Remarks:\n    // DELETE FROM UserModel WHERE (id >= 90)\n\n    /*\n        ## Multi-Table Query\n    */\n\n    mapper.Transaction ([&] ()\n    {\n        for (size_t i = 0; i < 50; i++)\n        {\n            mapper.Insert (\n                SellerModel { (int) i + 50,\n                \"Seller \" + std::to_string (i), 3.14 });\n            mapper.Insert (\n                OrderModel { 0,\n                (int) i / 2 + 50,\n                (int) i / 4 + 50,\n                \"Item \" + std::to_string (i),\n                i * 0.5 }, false);\n        }\n    });\n\n    // Join Tables for Query\n    auto joinedQuery = mapper.Query (UserModel {})\n        .Join (OrderModel {},\n            field (user.user_id) ==\n            field (order.user_id))\n        .LeftJoin (SellerModel {},\n            field (seller.seller_id) ==\n            field (order.seller_id))\n        .Where (field (user.user_id) >= 65);\n\n    // Get Result to List\n    auto result3 = joinedQuery.ToList ();\n\n    // Remarks:\n    // SELECT * FROM UserModel\n    //               JOIN OrderModel\n    //               ON UserModel.user_id=OrderModel.user_id\n    //               LEFT JOIN SellerModel\n    //               ON SellerModel.seller_id=OrderModel.seller_id\n    // WHERE (UserModel.user_id>=65)\n\n    // decltype (result3) == std::list<std::tuple<Nullable<..>, ..>>\n    // result3 = [(65, \"July_65\", 13, null, null, null,\n    //             31, 65, 57, \"Item 30\", 15,\n    //             57, \"Seller 7\", 3.14),\n    //            (65, \"July_65\", 13, null, null, null,\n    //             32, 65, 57, \"Item 31\", 15.5,\n    //             57, \"Seller 7\", 3.14),\n    //            ... ]\n\n    // Group & Having ~\n    auto result4 = joinedQuery\n        .Select (field (order.user_id),\n            field (user.user_name),\n            Avg (field (order.fee)))\n        .GroupBy (field (user.user_name))\n        .Having (Sum (field (order.fee)) >= 40.5)\n        .Skip (3)\n        .ToList ();\n\n    // Remarks:\n    // SELECT OrderModel.user_id,\n    //        UserModel.user_name,\n    //        AVG (OrderModel.fee)\n    // FROM UserModel\n    //      JOIN OrderModel\n    //      ON UserModel.user_id=OrderModel.user_id\n    //      LEFT JOIN SellerModel\n    //      ON SellerModel.seller_id=OrderModel.seller_id\n    // WHERE (UserModel.user_id>=65)\n    // GROUP BY UserModel.user_name\n    // HAVING SUM (OrderModel.fee)>=40.5\n    // LIMIT ~0 OFFSET 3\n\n    // decltype (result4) == std::list<std::tuple<Nullable<..>, ..>>\n    // result4 = [(73, \"July_73\", 23.25),\n    //            (74, \"July_74\", 24.25)]\n\n    // Compound Select\n    // Results are Nullable-Tuples\n    auto result5 = mapper.Query (OrderModel {})\n        .Select (field (order.product_name), field (order.user_id))\n        .Where (field (order.user_id) == 50)\n        .Union (\n            joinedQuery\n            .Select (field (user.user_name), field (order.order_id))\n        )\n        .Take (4)\n        .ToList ();\n\n    // Remarks:\n    // SELECT OrderModel.product_name,\n    //        OrderModel.user_id\n    // FROM OrderModel\n    //      WHERE (OrderModel.user_id==50)\n    // UNION\n    // SELECT UserModel.user_name,\n    //        OrderModel.order_id\n    // FROM UserModel\n    //      JOIN OrderModel\n    //      ON UserModel.user_id=OrderModel.user_id\n    //      LEFT JOIN SellerModel\n    //      ON SellerModel.seller_id=OrderModel.seller_id\n    //      WHERE (UserModel.user_id>=65)\n    // LIMIT 4;\n\n    // decltype (result5) == std::list<std::tuple<Nullable<..>, ..>>\n    // result5 = [(\"Item 0\", 50),\n    //            (\"Item 1\", 50),\n    //            (\"July_65\", 31),\n    //            (\"July_65\", 32)]\n\n    // ====================================================\n\n    // Output UserModel Objects\n    auto printUserModeles = [] (const auto &objs)\n    {\n        for (const auto& item : objs)\n        {\n            std::cout << item.user_id << \"\\t\" << item.credit_count\n                << \"\\t\" << item.user_name << \"\\t\";\n            PrintHelper::PrintNullable (item.age);\n            std::cout << \"\\t\";\n            PrintHelper::PrintNullable (item.salary);\n            std::cout << \"\\t\";\n            PrintHelper::PrintNullable (item.title);\n            std::cout << \"\\n\";\n        }\n        std::cout << std::endl;\n    };\n\n    // Sec 1\n    std::cout << \"\\n\";\n    printUserModeles (result1);\n\n    // Sec 2\n    printUserModeles (result2);\n    PrintHelper::PrintNullable (count);\n    std::cout << \"\\n\";\n    PrintHelper::PrintNullable (avg);\n    std::cout << \"\\n\" << std::endl;\n\n    // Sec 3\n    PrintHelper::PrintTuples (result3);\n    PrintHelper::PrintTuples (result4);\n    PrintHelper::PrintTuples (result5);\n\n    //std::cin.get ();\n    return 0;\n}\n"
  },
  {
    "path": "sample/sample.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1781A76A1F5FF9EE008E6067 /* sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1781A7691F5FF9EE008E6067 /* sample.cpp */; };\n\t\t1781A76F1F5FF9FC008E6067 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 1781A76D1F5FF9FC008E6067 /* sqlite3.c */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t1781A75D1F5FF992008E6067 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1781A75F1F5FF992008E6067 /* sample */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = sample; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1781A7691F5FF9EE008E6067 /* sample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sample.cpp; path = sample.cpp; sourceTree = \"<group>\"; };\n\t\t1781A76B1F5FF9FC008E6067 /* nullable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nullable.h; path = ../src/nullable.h; sourceTree = \"<group>\"; };\n\t\t1781A76C1F5FF9FC008E6067 /* ormlite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ormlite.h; path = ../src/ormlite.h; sourceTree = \"<group>\"; };\n\t\t1781A76D1F5FF9FC008E6067 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = ../src/sqlite3.c; sourceTree = \"<group>\"; };\n\t\t1781A76E1F5FF9FC008E6067 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = ../src/sqlite3.h; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t1781A75C1F5FF992008E6067 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t1781A7561F5FF992008E6067 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1781A76B1F5FF9FC008E6067 /* nullable.h */,\n\t\t\t\t1781A76C1F5FF9FC008E6067 /* ormlite.h */,\n\t\t\t\t1781A76D1F5FF9FC008E6067 /* sqlite3.c */,\n\t\t\t\t1781A76E1F5FF9FC008E6067 /* sqlite3.h */,\n\t\t\t\t1781A7691F5FF9EE008E6067 /* sample.cpp */,\n\t\t\t\t1781A7601F5FF992008E6067 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1781A7601F5FF992008E6067 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1781A75F1F5FF992008E6067 /* sample */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t1781A75E1F5FF992008E6067 /* sample */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1781A7661F5FF992008E6067 /* Build configuration list for PBXNativeTarget \"sample\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t1781A75B1F5FF992008E6067 /* Sources */,\n\t\t\t\t1781A75C1F5FF992008E6067 /* Frameworks */,\n\t\t\t\t1781A75D1F5FF992008E6067 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = sample;\n\t\t\tproductName = sample;\n\t\t\tproductReference = 1781A75F1F5FF992008E6067 /* sample */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t1781A7571F5FF992008E6067 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0830;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t1781A75E1F5FF992008E6067 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.3.3;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 1781A75A1F5FF992008E6067 /* Build configuration list for PBXProject \"sample\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 1781A7561F5FF992008E6067;\n\t\t\tproductRefGroup = 1781A7601F5FF992008E6067 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t1781A75E1F5FF992008E6067 /* sample */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t1781A75B1F5FF992008E6067 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1781A76A1F5FF9EE008E6067 /* sample.cpp in Sources */,\n\t\t\t\t1781A76F1F5FF9FC008E6067 /* sqlite3.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1781A7641F5FF992008E6067 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1781A7651F5FF992008E6067 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1781A7671F5FF992008E6067 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1781A7681F5FF992008E6067 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1781A75A1F5FF992008E6067 /* Build configuration list for PBXProject \"sample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1781A7641F5FF992008E6067 /* Debug */,\n\t\t\t\t1781A7651F5FF992008E6067 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1781A7661F5FF992008E6067 /* Build configuration list for PBXNativeTarget \"sample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1781A7671F5FF992008E6067 /* Debug */,\n\t\t\t\t1781A7681F5FF992008E6067 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 1781A7571F5FF992008E6067 /* Project object */;\n}\n"
  },
  {
    "path": "sample/sample.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{AC415D81-EA1D-43F3-A741-60ED85136D48}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>sample</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>$(SolutionDir)$(Configuration)\\sample\\</OutDir>\n    <IntDir>$(Configuration)\\sample\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IntDir>$(Platform)\\$(Configuration)\\sample\\</IntDir>\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\sample\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalOptions>/std:c++14 %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\src\\sqlite3.c\" />\n    <ClCompile Include=\"sample.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\src\\ormlite.h\" />\n    <ClInclude Include=\"..\\src\\nullable.h\" />\n    <ClInclude Include=\"..\\src\\sqlite3.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "src/nullable.h",
    "content": "\n// Nullable module for ORM Lite\n// ORM Lite - An ORM for SQLite in C++ 17\n// https://github.com/BOT-Man-JL/ORM-Lite\n// BOT Man, 2017\n\n\n#ifndef BOT_ORM_NULLABLE_H\n#define BOT_ORM_NULLABLE_H\n\n// std::nullptr_t\n#include <cstddef>\n\n// Nullable Template\n// https://stackoverflow.com/questions/2537942/nullable-values-in-c/28811646#28811646\n\nnamespace BOT_ORM\n{\n    template <typename T>\n    class Nullable\n    {\n        template <typename T2>\n        friend bool operator== (const Nullable<T2> &op1,\n            const Nullable<T2> &op2);\n        template <typename T2>\n        friend bool operator== (const Nullable<T2> &op,\n            const T2 &value);\n        template <typename T2>\n        friend bool operator== (const T2 &value,\n            const Nullable<T2> &op);\n        template <typename T2>\n        friend bool operator== (const Nullable<T2> &op,\n            std::nullptr_t);\n        template <typename T2>\n        friend bool operator== (std::nullptr_t,\n            const Nullable<T2> &op);\n    public:\n        // Default or Null Construction\n        Nullable ()\n            : m_hasValue (false), m_value (T ())\n        {}\n        Nullable (std::nullptr_t)\n            : Nullable ()\n        {}\n\n        // Null Assignment\n        const Nullable<T> & operator= (std::nullptr_t)\n        {\n            m_hasValue = false;\n            m_value = T ();\n            return *this;\n        }\n\n        // Value Construction\n        template<typename T2>\n        Nullable (const T2 &value)\n            : m_hasValue (true), m_value (value)\n        {}\n\n        // Value Assignment\n        template<typename T2>\n        const Nullable<T> & operator= (const T2 &value)\n        {\n            m_hasValue = true;\n            m_value = value;\n            return *this;\n        }\n\n    private:\n        bool m_hasValue;\n        T m_value;\n\n    public:\n        const T &Value () const\n        {\n            return m_value;\n        }\n    };\n\n    // == varialbe\n    template <typename T2>\n    inline bool operator== (const Nullable<T2> &op1,\n        const Nullable<T2> &op2)\n    {\n        return op1.m_hasValue == op2.m_hasValue &&\n            (!op1.m_hasValue || op1.m_value == op2.m_value);\n    }\n\n    // == value\n    template <typename T2>\n    inline bool operator== (const Nullable<T2> &op,\n        const T2 &value)\n    {\n        return op.m_hasValue && op.m_value == value;\n    }\n    template <typename T2>\n    inline bool operator== (const T2 &value,\n        const Nullable<T2> &op)\n    {\n        return op.m_hasValue && op.m_value == value;\n    }\n\n    // == nullptr\n    template <typename T2>\n    inline bool operator== (const Nullable<T2> &op,\n        std::nullptr_t)\n    {\n        return !op.m_hasValue;\n    }\n    template <typename T2>\n    inline bool operator== (std::nullptr_t,\n        const Nullable<T2> &op)\n    {\n        return !op.m_hasValue;\n    }\n}\n\n#endif // !BOT_ORM_NULLABLE_H\n"
  },
  {
    "path": "src/ormlite.h",
    "content": "\n// ORM Lite\n// An ORM for SQLite in C++ 14\n// https://github.com/BOT-Man-JL/ORM-Lite\n// BOT Man, 2017\n\n#ifndef BOT_ORM_H\n#define BOT_ORM_H\n\n// Container\n#include <tuple>\n#include <vector>\n#include <list>\n#include <string>\n#include <unordered_map>\n\n// Serialization\n#include <sstream>\n\n// Type Traits\n#include <type_traits>\n\n// std::shared_ptr\n#include <memory>\n\n// for Field Name Extractor\n#include <cctype>\n\n// for SQL Connector\n#include <thread>\n#include <functional>\n\n// SQLite 3 Dependency\n#include \"sqlite3.h\"\n\n// Nullable Module\n#include \"nullable.h\"\n\n// Public Macro\n\n#define ORMAP(_TABLE_NAME_, ...)                          \\\nprivate:                                                  \\\nfriend class BOT_ORM_Impl::InjectionHelper;               \\\ntemplate <typename FN>                                    \\\ninline decltype (auto) __Accept (FN fn)                   \\\n{ return fn (__VA_ARGS__); }                              \\\ntemplate <typename FN>                                    \\\ninline decltype (auto) __Accept (FN fn) const             \\\n{ return fn (__VA_ARGS__); }                              \\\nconstexpr static const char *__FieldNames = #__VA_ARGS__; \\\nconstexpr static const char *__TableName =  _TABLE_NAME_; \\\n\n// Private Macros\n\n#define NO_ORMAP \"Please Inject the Class with 'ORMAP' first\"\n#define BAD_TYPE \"Only Support Integral, Floating Point and std::string\"\n\n#define BAD_COLUMN_COUNT \"Bad Column Count\"\n#define NULL_DESERIALIZE \"Get Null Value\"\n\n#define NO_FIELD \"No Such Field for current Extractor\"\n#define NOT_SAME_TABLE \"Fields are NOT from the Same Table\"\n\n// Helpers\n\nnamespace BOT_ORM_Impl\n{\n    // Naive SQL Driver (Todo: Improved Later)\n\n    class SQLConnector\n    {\n    public:\n        SQLConnector (const std::string &fileName)\n        {\n            if (sqlite3_open (fileName.c_str (), &db) != SQLITE_OK)\n                throw std::runtime_error (\n                    std::string (\"SQL error: Can't open database '\")\n                    + sqlite3_errmsg (db) + \"'\");\n        }\n\n        ~SQLConnector ()\n        {\n            sqlite3_close (db);\n        }\n\n        void Execute (const std::string &cmd)\n        {\n            char *zErrMsg = 0;\n            int rc = SQLITE_OK;\n\n            for (size_t iTry = 0; iTry < MAX_TRIAL; iTry++)\n            {\n                rc = sqlite3_exec (db, cmd.c_str (), 0, 0, &zErrMsg);\n                if (rc != SQLITE_BUSY)\n                    break;\n\n                std::this_thread::sleep_for (\n                    std::chrono::microseconds (20));\n            }\n\n            if (rc != SQLITE_OK)\n            {\n                auto errStr = std::string (\"SQL error: '\") + zErrMsg\n                    + \"' at '\" + cmd + \"'\";\n                sqlite3_free (zErrMsg);\n                throw std::runtime_error (errStr);\n            }\n        }\n\n        void ExecuteCallback (const std::string &cmd,\n            std::function<void (int, char **)>\n            callback)\n        {\n            char *zErrMsg = 0;\n            int rc = SQLITE_OK;\n\n            auto callbackParam = std::make_pair (&callback, std::string {});\n\n            for (size_t iTry = 0; iTry < MAX_TRIAL; iTry++)\n            {\n                rc = sqlite3_exec (db, cmd.c_str (), CallbackWrapper,\n                    &callbackParam, &zErrMsg);\n                if (rc != SQLITE_BUSY)\n                    break;\n\n                std::this_thread::sleep_for (\n                    std::chrono::microseconds (20));\n            }\n\n            if (rc == SQLITE_ABORT)\n            {\n                auto errStr = \"SQL error: '\" + callbackParam.second +\n                    \"' at '\" + cmd + \"'\";\n                sqlite3_free (zErrMsg);\n                throw std::runtime_error (errStr);\n            }\n            else if (rc != SQLITE_OK)\n            {\n                auto errStr = std::string (\"SQL error: '\") + zErrMsg\n                    + \"' at '\" + cmd + \"'\";\n                sqlite3_free (zErrMsg);\n                throw std::runtime_error (errStr);\n            }\n        }\n\n    private:\n        sqlite3 *db;\n        constexpr static size_t MAX_TRIAL = 16;\n\n        static int CallbackWrapper (\n            void *callbackParam, int argc, char **argv, char **)\n        {\n            auto pParam = static_cast<std::pair<\n                std::function<void (int, char **)> *,\n                std::string\n            >*>(callbackParam);\n\n            try\n            {\n                pParam->first->operator()(argc, argv);\n                return 0;\n            }\n            catch (const std::exception &ex)\n            {\n                pParam->second = ex.what ();\n                return 1;\n            }\n        }\n    };\n\n    // Helper - Field Type Checker\n\n    template <typename T>\n    struct TypeString\n    {\n        constexpr static const char *typeStr =\n            (std::is_integral<T>::value &&\n                !std::is_same<T, char>::value &&\n                !std::is_same<T, wchar_t>::value &&\n                !std::is_same<T, char16_t>::value &&\n                !std::is_same<T, char32_t>::value &&\n                !std::is_same<T, unsigned char>::value)\n            ? \" integer not null\"\n            : (std::is_floating_point<T>::value)\n            ? \" real not null\"\n            : (std::is_same<T, std::string>::value)\n            ? \" text not null\"\n            : nullptr;\n\n        static_assert (typeStr != nullptr, BAD_TYPE);\n    };\n\n    template <typename T>\n    struct TypeString <BOT_ORM::Nullable<T>>\n    {\n        constexpr static const char *typeStr =\n            (std::is_integral<T>::value &&\n                !std::is_same<T, char>::value &&\n                !std::is_same<T, wchar_t>::value &&\n                !std::is_same<T, char16_t>::value &&\n                !std::is_same<T, char32_t>::value &&\n                !std::is_same<T, unsigned char>::value)\n            ? \" integer\"\n            : (std::is_floating_point<T>::value)\n            ? \" real\"\n            : (std::is_same<T, std::string>::value)\n            ? \" text\"\n            : nullptr;\n\n        static_assert (typeStr != nullptr, BAD_TYPE);\n    };\n\n    // Serialization Helper\n\n    struct SerializationHelper\n    {\n        template <typename T>\n        static inline\n            std::enable_if_t<TypeString<T>::typeStr == nullptr, bool>\n            Serialize (std::ostream &, const T &)\n        {}\n        template <typename T>\n        static inline\n            std::enable_if_t<TypeString<T>::typeStr != nullptr, bool>\n            Serialize (std::ostream &os, const T &value)\n        {\n            os << value;\n            return true;\n        }\n\n        static inline bool Serialize (std::ostream &os,\n            const std::string &value)\n        {\n            os << \"'\" << value << \"'\";\n            return true;\n        }\n\n        template <typename T>\n        static inline bool Serialize (\n            std::ostream &os,\n            const BOT_ORM::Nullable<T> &value)\n        {\n            if (value == nullptr)\n                return false;\n            return Serialize (os, value.Value ());\n        }\n    };\n\n    // Deserialization Helper\n\n    struct DeserializationHelper\n    {\n        template <typename T>\n        static inline std::enable_if_t<TypeString<T>::typeStr == nullptr>\n            Deserialize (T &, const char *)\n        {}\n        template <typename T>\n        static inline std::enable_if_t<TypeString<T>::typeStr != nullptr>\n            Deserialize (T &property, const char *value)\n        {\n            if (value) std::istringstream { value } >> property;\n            else throw std::runtime_error (NULL_DESERIALIZE);\n        }\n\n        static inline void Deserialize (std::string &property,\n            const char *value)\n        {\n            if (value) property = value;\n            else throw std::runtime_error (NULL_DESERIALIZE);\n        }\n\n        template <typename T>\n        static inline void Deserialize (\n            BOT_ORM::Nullable<T> &property, const char *value)\n        {\n            if (value)\n            {\n                T val;\n                Deserialize (val, value);\n                property = val;\n            }\n            else\n                property = nullptr;\n        }\n    };\n\n    // Injection Helper\n\n    class InjectionHelper\n    {\n        static std::vector<std::string> ExtractFieldName (std::string input)\n        {\n            std::vector<std::string> ret;\n            std::string tmpStr;\n\n            for (char ch : std::move (input) + \",\")\n            {\n                if (isalnum (ch) || ch == '_')\n                    tmpStr += ch;\n                else if (ch == ',')\n                {\n                    if (!tmpStr.empty ())\n                        ret.push_back (tmpStr);\n                    tmpStr.clear ();\n                }\n            }\n            return ret;\n        };\n\n    public:\n        // Checking Injection\n        template <typename T> class HasInjected\n        {\n            template <typename...> struct make_void { using type = void; };\n            template <typename... _Types>\n            using void_t = typename make_void<_Types...>::type;\n\n            template <typename, typename = void_t<>>\n            struct Test : std::false_type {};\n            template <typename U>\n            struct Test <U, void_t<decltype (U::__TableName)>>\n                : std::true_type\n            {};\n\n        public:\n            static constexpr bool value = Test<T>::value;\n\n            static_assert (value, NO_ORMAP);\n        };\n\n        // Proxy Function\n        template <typename C, typename Fn>\n        static inline decltype (auto) Visit (C &obj, Fn fn)\n        {\n            return obj.__Accept (fn);\n        }\n\n        // Field Name Proxy\n        template <typename C>\n        static inline const std::vector<std::string> &FieldNames (const C &)\n        {\n            static const auto fieldNames = ExtractFieldName (C::__FieldNames);\n            return fieldNames;\n        }\n\n        // Table Name Proxy\n        template <typename C>\n        static inline const std::string &TableName (const C &)\n        {\n            static const std::string tableName { C::__TableName };\n            return tableName;\n        }\n    };\n\n    // Unpacking Tricks :-)\n    // http://stackoverflow.com/questions/26902633/how-to-iterate-over-a-tuple-in-c-11/26902803#26902803\n    // - To avoid the unspecified order,\n    //   brace-enclosed initializer lists can be used,\n    //   which guarantee strict left-to-right order of evaluation.\n    // - To avoid the need for a not void return type,\n    //   the comma operator can be used to\n    //   always yield 1 in each expansion element.\n\n    using Expander = int[];\n}\n\nnamespace BOT_ORM\n{\n    namespace Expression\n    {\n        // SetExpr\n\n        struct SetExpr\n        {\n            SetExpr (std::string field_op_val)\n                : _expr { std::move (field_op_val) }\n            {}\n\n            const std::string &ToString () const\n            {\n                return _expr;\n            }\n\n            inline SetExpr operator && (const SetExpr &rhs) const\n            {\n                return SetExpr { _expr + \",\" + rhs._expr };\n            }\n\n        private:\n            std::string _expr;\n        };\n\n        // Selectable\n\n        template <typename T>\n        struct Selectable\n        {\n            std::string fieldName;\n            const std::string *tableName;\n\n            Selectable (std::string _fieldName,\n                const std::string *_tableName)\n                : fieldName (std::move (_fieldName)), tableName (_tableName)\n            {}\n        };\n\n        // Field : Selectable\n\n        template <typename T>\n        struct Field : public Selectable<T>\n        {\n            Field (std::string _fieldName,\n                const std::string *_tableName)\n                : Selectable<T> (std::move (_fieldName), _tableName) {}\n\n            inline SetExpr operator = (T value)\n            {\n                std::ostringstream os;\n                BOT_ORM_Impl::SerializationHelper::\n                    Serialize (os << this->fieldName << \"=\", value);\n                return SetExpr { os.str () };\n            }\n        };\n\n        // Nullable Field : Field : Selectable\n\n        template <typename T>\n        struct NullableField : public Field<T>\n        {\n            NullableField (std::string _fieldName,\n                const std::string *_tableName)\n                : Field<T> (std::move (_fieldName), _tableName) {}\n\n            inline SetExpr operator = (T value)\n            {\n                std::ostringstream os;\n                BOT_ORM_Impl::SerializationHelper::\n                    Serialize (os << this->fieldName << \"=\", value);\n                return SetExpr { os.str () };\n            }\n\n            inline SetExpr operator = (std::nullptr_t)\n            {\n                return SetExpr { this->fieldName + \"=null\" };\n            }\n        };\n\n        // Aggregate Function : Selectable\n\n        template <typename T>\n        struct Aggregate : public Selectable<T>\n        {\n            Aggregate (std::string function)\n                : Selectable<T> (std::move (function), nullptr) {}\n\n            Aggregate (std::string function, const Field<T> &field)\n                : Selectable<T> (std::move (function) + \"(\" +\n                    *(field.tableName) + \".\" +\n                    field.fieldName + \")\", nullptr)\n            {}\n        };\n\n        // Expr\n\n        struct Expr\n        {\n            template <typename T>\n            Expr (const Selectable<T> &field, std::string op_val)\n                : _exprs { { field.fieldName + op_val, field.tableName } }\n            {}\n\n            template <typename T>\n            Expr (const Selectable<T> &field, std::string op, T value)\n            {\n                std::ostringstream os;\n                BOT_ORM_Impl::SerializationHelper::\n                    Serialize (os << field.fieldName << op, value);\n                _exprs.emplace_back (os.str (), field.tableName);\n            }\n\n            template <typename T>\n            Expr (const Field<T> &field1,\n                std::string op,\n                const Field<T> &field2)\n                : _exprs\n            {\n                { field1.fieldName, field1.tableName },\n                { std::move (op), nullptr },\n                { field2.fieldName, field2.tableName }\n            }\n            {}\n\n            std::string ToString () const\n            {\n                std::ostringstream out;\n                for (const auto &expr : _exprs)\n                {\n                    if (expr.second != nullptr)\n                        out << *(expr.second) << \".\";\n                    out << expr.first;\n                }\n                return out.str ();\n            }\n\n            inline Expr operator && (const Expr &rhs) const\n            {\n                return And_Or (rhs, \" and \");\n            }\n            inline Expr operator || (const Expr &rhs) const\n            {\n                return And_Or (rhs, \" or \");\n            }\n\n        private:\n            std::list<std::pair<std::string, const std::string *>> _exprs;\n\n            Expr And_Or (const Expr &rhs, std::string logOp) const\n            {\n                auto ret = *this;\n                auto rigthExprs = rhs._exprs;\n                ret._exprs.emplace_front (\"(\", nullptr);\n                ret._exprs.emplace_back (std::move (logOp), nullptr);\n                ret._exprs.splice (ret._exprs.cend (),\n                    std::move (rigthExprs));\n                ret._exprs.emplace_back (\")\", nullptr);\n                return ret;\n            }\n        };\n\n        // Field / Aggregate ? Value\n\n        template <typename T>\n        inline Expr operator == (const Selectable<T> &op, T value)\n        {\n            return Expr (op, \"=\", std::move (value));\n        }\n\n        template <typename T>\n        inline Expr operator != (const Selectable<T> &op, T value)\n        {\n            return Expr (op, \"!=\", std::move (value));\n        }\n\n        template <typename T>\n        inline Expr operator > (const Selectable<T> &op, T value)\n        {\n            return Expr (op, \">\", std::move (value));\n        }\n\n        template <typename T>\n        inline Expr operator >= (const Selectable<T> &op, T value)\n        {\n            return Expr (op, \">=\", std::move (value));\n        }\n\n        template <typename T>\n        inline Expr operator < (const Selectable<T> &op, T value)\n        {\n            return Expr (op, \"<\", std::move (value));\n        }\n\n        template <typename T>\n        inline Expr operator <= (const Selectable<T> &op, T value)\n        {\n            return Expr (op, \"<=\", std::move (value));\n        }\n\n        // Field ? Field\n\n        template <typename T>\n        inline Expr operator == (const Field<T> &op1, const Field<T> &op2)\n        {\n            return Expr { op1 , \"=\", op2 };\n        }\n\n        template <typename T>\n        inline Expr operator != (const Field<T> &op1, const Field<T> &op2)\n        {\n            return Expr { op1, \"!=\", op2 };\n        }\n\n        template <typename T>\n        inline Expr operator > (const Field<T> &op1, const Field<T> &op2)\n        {\n            return Expr { op1 , \">\", op2 };\n        }\n\n        template <typename T>\n        inline Expr operator >= (const Field<T> &op1, const Field<T> &op2)\n        {\n            return Expr { op1, \">=\", op2 };\n        }\n\n        template <typename T>\n        inline Expr operator < (const Field<T> &op1, const Field<T> &op2)\n        {\n            return Expr { op1 , \"<\", op2 };\n        }\n\n        template <typename T>\n        inline Expr operator <= (const Field<T> &op1, const Field<T> &op2)\n        {\n            return Expr { op1, \"<=\", op2 };\n        }\n\n        // Nullable Field == / != nullptr\n\n        template <typename T>\n        inline Expr operator == (const NullableField<T> &op, std::nullptr_t)\n        {\n            return Expr { op, \" is null\" };\n        }\n\n        template <typename T>\n        inline Expr operator != (const NullableField<T> &op, std::nullptr_t)\n        {\n            return Expr { op, \" is not null\" };\n        }\n\n        // String Field & / | std::string\n\n        inline Expr operator & (const Field<std::string> &field,\n            std::string val)\n        {\n            return Expr (field, \" like \", std::move (val));\n        }\n\n        inline Expr operator | (const Field<std::string> &field,\n            std::string val)\n        {\n            return Expr (field, \" not like \", std::move (val));\n        }\n\n        // Aggregate Function Helpers\n\n        inline auto Count ()\n        {\n            return Aggregate<size_t> { \"count (*)\" };\n        }\n\n        template <typename T>\n        inline auto Count (const Field<T> &field)\n        {\n            return Aggregate<T> { \"count\", field };\n        }\n\n        template <typename T>\n        inline auto Sum (const Field<T> &field)\n        {\n            return Aggregate<T> { \"sum\", field };\n        }\n\n        template <typename T>\n        inline auto Avg (const Field<T> &field)\n        {\n            return Aggregate<T> { \"avg\", field };\n        }\n\n        template <typename T>\n        inline auto Max (const Field<T> &field)\n        {\n            return Aggregate<T> { \"max\", field };\n        }\n\n        template <typename T>\n        inline auto Min (const Field<T> &field)\n        {\n            return Aggregate<T> { \"min\", field };\n        }\n    }\n\n    class ORMapper;\n\n    class Constraint\n    {\n    protected:\n        std::string constraint;\n        std::string field;\n\n        Constraint (std::string &&_constraint,\n            std::string _field = std::string {})\n            : constraint (_constraint), field (std::move (_field))\n        {}\n\n        friend class ORMapper;\n\n    public:\n        struct CompositeField\n        {\n            std::string fieldName;\n            const std::string *tableName;\n\n            template <typename... Fields>\n            CompositeField (const Fields & ... args)\n                : tableName (nullptr)\n            {\n                (void) BOT_ORM_Impl::Expander\n                {\n                    0, (Extract (args), 0)...\n                };\n            }\n\n        private:\n            template <typename T>\n            void Extract (const Expression::Field<T> &field)\n            {\n                if (tableName != nullptr && tableName != field.tableName)\n                    throw std::runtime_error (NOT_SAME_TABLE);\n                tableName = field.tableName;\n                if (fieldName.empty ())\n                    fieldName = field.fieldName;\n                else\n                    fieldName = field.fieldName + \",\" + fieldName;\n            }\n        };\n\n        template <typename T>\n        static inline Constraint Default (\n            const Expression::Field<T> &field,\n            const T &value)\n        {\n            std::ostringstream os;\n            BOT_ORM_Impl::SerializationHelper::\n                Serialize (os << \" default \", value);\n            return Constraint { os.str (), field.fieldName };\n        }\n\n        static inline Constraint Check (\n            const Expression::Expr &expr)\n        {\n            return Constraint { \"check (\" + expr.ToString () + \")\" };\n        }\n\n        template <typename T>\n        static inline Constraint Unique (\n            const Expression::Field<T> &field)\n        {\n            return Constraint { \"unique (\" + field.fieldName + \")\" };\n        }\n\n        static inline Constraint Unique (\n            const CompositeField &fields)\n        {\n            return Constraint { \"unique (\" + fields.fieldName + \")\" };\n        }\n\n        template <typename T>\n        static inline Constraint Reference (\n            const Expression::Field<T> &field,\n            const Expression::Field<T> &refered)\n        {\n            return Constraint {\n                std::string (\"foreign key (\") + field.fieldName +\n                \") references \" + *(refered.tableName) +\n                \"(\" + refered.fieldName + \")\" };\n        }\n\n        static inline Constraint Reference (\n            const CompositeField &field,\n            const CompositeField &refered)\n        {\n            return Constraint {\n                std::string (\"foreign key (\") + field.fieldName +\n                \") references \" + *(refered.tableName) +\n                \"(\" + refered.fieldName + \")\" };\n        }\n    };\n\n    template <typename T>\n    class Queryable;\n}\n\nnamespace BOT_ORM_Impl\n{\n    // Why Remove QueryableHelper from Query?\n    // Query is a template but the Helper can be shared\n\n    class QueryableHelper\n    {\n        template <typename T>\n        using Nullable = BOT_ORM::Nullable<T>;\n\n        template <typename T>\n        using Selectable = BOT_ORM::Expression::Selectable<T>;\n\n    protected:\n        template <typename T>\n        friend class BOT_ORM::Queryable;\n\n        // #1 Tuple Visitor\n\n        // Apply 'Fn' to each of element of Tuple\n        template <typename Fn, typename TupleType, std::size_t... I>\n        static inline void TupleVisit_Impl (\n            TupleType &tuple, Fn fn, std::index_sequence<I...>)\n        {\n            (void) BOT_ORM_Impl::Expander\n            {\n                0, ((void) fn (std::get<I> (tuple)), 0)...\n            };\n        }\n\n        // Produce the 'index_sequence' for 'tuple'\n        template <typename Fn, typename TupleType>\n        static inline void TupleVisit (TupleType &tuple, Fn fn)\n        {\n            constexpr auto size = std::tuple_size<TupleType>::value;\n            return TupleVisit_Impl (tuple, fn,\n                std::make_index_sequence<size> {});\n        }\n\n        // #2 Join To Tuple\n\n        // Type To Nullable\n        // Get Nullable Type Wrappers for Non-nullable Types\n        template <typename T> struct TypeToNullable\n        {\n            using type = Nullable<T>;\n        };\n        template <typename T> struct TypeToNullable <Nullable<T>>\n        {\n            using type = Nullable<T>;\n        };\n\n        // Fields To Nullable\n        // Apply 'TypeToNullable' to each element of Fields\n        template <typename... Args>\n        static inline auto FieldsToNullable (Args...)\n        {\n            // Unpacking Tricks :-)\n            // Expand each of 'Args'\n            // with 'TypeToNullable_t<...>' as a sequence\n            return std::tuple<\n                typename TypeToNullable<Args>::type...\n            > {};\n        }\n\n        // QueryResult To Nullable\n        template <typename C>\n        static inline auto QueryResultToTuple (const C &arg)\n        {\n            return BOT_ORM_Impl::InjectionHelper::Visit (\n                arg, [] (auto ... args)\n            {\n                return FieldsToNullable (args...);\n            });\n        }\n\n        template <typename... Args>\n        static inline auto QueryResultToTuple (\n            const std::tuple<Args...>& t)\n        {\n            // FieldsToNullable is not necessary: Nullable already\n            return t;\n        }\n\n        // Construct Tuple from QueryResult List\n        template <typename... Args>\n        static inline auto JoinToTuple (const Args & ... args)\n        {\n            // Unpacking Tricks :-)\n            return decltype (std::tuple_cat (\n                QueryResultToTuple (args)...\n            )) {};\n        }\n\n        // #3 Select To Tuple\n\n        // Selectable To Tuple\n        template <typename T>\n        static inline auto SelectableToTuple (const Selectable<T> &)\n        {\n            // Notes: Only 'const Selectable<T> &' will overload...\n            return Nullable<T> {};\n        }\n\n        // Construct Tuple from Selectable<T> List\n        template <typename... Args>\n        static inline auto SelectToTuple (const Args & ... args)\n        {\n            // Unpacking Tricks :-)\n            return std::tuple <\n                decltype (SelectableToTuple (args))...\n            > {};\n        }\n\n        // #4 Field To SQL\n\n        // Return Field Strings for GroupBy, OrderBy and Select\n        template <typename T>\n        static inline std::string FieldToSql (const Selectable<T> &op)\n        {\n            if (op.tableName) return (*op.tableName) + \".\" + op.fieldName;\n            else return op.fieldName;\n        }\n        template <typename T, typename... Args>\n        static inline std::string FieldToSql (const Selectable<T> &arg,\n            const Args & ... args)\n        {\n            return FieldToSql (arg) + \",\" + FieldToSql (args...);\n        }\n    };\n}\n\nnamespace BOT_ORM\n{\n    // Queryable\n\n    template <typename QueryResult>\n    class Queryable\n    {\n        template <typename C>\n        using HasInjected =\n            BOT_ORM_Impl::InjectionHelper::HasInjected<C>;\n\n    protected:\n        std::shared_ptr<BOT_ORM_Impl::SQLConnector> _connector;\n        QueryResult _queryHelper;\n\n        std::string _sqlFrom;\n        std::string _sqlSelect;\n        std::string _sqlTarget;\n\n        std::string _sqlWhere;\n        std::string _sqlGroupBy;\n        std::string _sqlHaving;\n\n        std::string _sqlOrderBy;\n        std::string _sqlLimit;\n        std::string _sqlOffset;\n\n        Queryable (\n            std::shared_ptr<BOT_ORM_Impl::SQLConnector> connector,\n            QueryResult queryHelper,\n            std::string sqlFrom,\n            std::string sqlSelect = \"select \",\n            std::string sqlTarget = \"*\",\n            std::string sqlWhere = std::string {},\n            std::string sqlGroupBy = std::string {},\n            std::string sqlHaving = std::string {},\n            std::string sqlOrderBy = std::string {},\n            std::string sqlLimit = std::string {},\n            std::string sqlOffset = std::string {})\n            :\n            _connector (std::move (connector)),\n            _queryHelper (std::move (queryHelper)),\n            _sqlFrom (std::move (sqlFrom)),\n            _sqlSelect (std::move (sqlSelect)),\n            _sqlTarget (std::move (sqlTarget)),\n            _sqlWhere (std::move (sqlWhere)),\n            _sqlGroupBy (std::move (sqlGroupBy)),\n            _sqlHaving (std::move (sqlHaving)),\n            _sqlOrderBy (std::move (sqlOrderBy)),\n            _sqlLimit (std::move (sqlLimit)),\n            _sqlOffset (std::move (sqlOffset))\n        {}\n\n        template <typename Q> friend class Queryable;\n        friend class ORMapper;\n\n    public:\n        // Distinct\n        inline Queryable Distinct () const &\n        {\n            auto ret = *this;\n            ret._sqlSelect = \"select distinct \";\n            return ret;\n        }\n        inline Queryable Distinct () &&\n        {\n            (*this)._sqlSelect = \"select distinct \";\n            return std::move (*this);\n        }\n\n        // Where\n        inline Queryable Where (const Expression::Expr &expr) const &\n        {\n            auto ret = *this;\n            ret._sqlWhere = \" where (\" + expr.ToString () + \")\";\n            return ret;\n        }\n        inline Queryable Where (const Expression::Expr &expr) &&\n        {\n            (*this)._sqlWhere = \" where (\" + expr.ToString () + \")\";\n            return std::move (*this);\n        }\n\n        // Group By\n        template <typename T>\n        inline Queryable GroupBy (const Expression::Field<T> &field) const &\n        {\n            auto ret = *this;\n            ret._sqlGroupBy = \" group by \" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field);\n            return ret;\n        }\n        template <typename T>\n        inline Queryable GroupBy (const Expression::Field<T> &field) &&\n        {\n            (*this)._sqlGroupBy = \" group by \" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field);\n            return std::move (*this);\n        }\n\n        // Having\n        inline Queryable Having (const Expression::Expr &expr) const &\n        {\n            auto ret = *this;\n            ret._sqlHaving = \" having \" + expr.ToString ();\n            return ret;\n        }\n        inline Queryable Having (const Expression::Expr &expr) &&\n        {\n            (*this)._sqlHaving = \" having \" + expr.ToString ();\n            return std::move (*this);\n        }\n\n        // Limit\n        inline Queryable Take (size_t count) const &\n        {\n            auto ret = *this;\n            ret._sqlLimit = \" limit \" + std::to_string (count);\n            return ret;\n        }\n        inline Queryable Take (size_t count) &&\n        {\n            (*this)._sqlLimit = \" limit \" + std::to_string (count);\n            return std::move (*this);\n        }\n\n        // Offset\n        inline Queryable Skip (size_t count) const &\n        {\n            auto ret = *this;\n            if (ret._sqlLimit.empty ())\n                ret._sqlLimit = \" limit ~0\";  // ~0 is a trick :-)\n            ret._sqlOffset = \" offset \" + std::to_string (count);\n            return ret;\n        }\n        inline Queryable Skip (size_t count) &&\n        {\n            if ((*this)._sqlLimit.empty ())\n                (*this)._sqlLimit = \" limit ~0\";  // ~0 is a trick :-)\n            (*this)._sqlOffset = \" offset \" + std::to_string (count);\n            return std::move (*this);\n        }\n\n        // Order By\n        template <typename T>\n        inline Queryable OrderBy (\n            const Expression::Field<T> &field) const &\n        {\n            auto ret = *this;\n            if (ret._sqlOrderBy.empty ())\n                ret._sqlOrderBy = \" order by \" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field);\n            else\n                ret._sqlOrderBy += \",\" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field);\n            return ret;\n        }\n        template <typename T>\n        inline Queryable OrderBy (\n            const Expression::Field<T> &field) &&\n        {\n            if ((*this)._sqlOrderBy.empty ())\n                (*this)._sqlOrderBy = \" order by \" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field);\n            else\n                (*this)._sqlOrderBy += \",\" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field);\n            return std::move (*this);\n        }\n\n        // Order By Desc\n        template <typename T>\n        inline Queryable OrderByDescending (\n            const Expression::Field<T> &field) const &\n        {\n            auto ret = *this;\n            if (ret._sqlOrderBy.empty ())\n                ret._sqlOrderBy = \" order by \" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field) + \" desc\";\n            else\n                ret._sqlOrderBy += \",\" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field) + \" desc\";\n            return ret;\n        }\n        template <typename T>\n        inline Queryable OrderByDescending (\n            const Expression::Field<T> &field) &&\n        {\n            if ((*this)._sqlOrderBy.empty ())\n                (*this)._sqlOrderBy = \" order by \" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field) + \" desc\";\n            else\n                (*this)._sqlOrderBy += \",\" +\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (field) + \" desc\";\n            return std::move (*this);\n        }\n\n        // Select\n        template <typename... Args>\n        inline auto Select (const Args & ... args) const\n        {\n            return _NewQuery (\n                BOT_ORM_Impl::QueryableHelper::FieldToSql (args...),\n                _sqlFrom,\n                BOT_ORM_Impl::QueryableHelper::SelectToTuple (args...)\n            );\n        }\n\n        // Join\n        template <typename C>\n        inline auto Join (const C &,\n            const Expression::Expr &,\n            std::enable_if_t<\n            !HasInjected<C>::value>\n            * = nullptr) const\n        {}\n        template <typename C>\n        inline auto Join (const C &queryHelper2,\n            const Expression::Expr &onExpr,\n            std::enable_if_t<\n            HasInjected<C>::value>\n            * = nullptr) const\n        {\n            return _NewJoinQuery (queryHelper2, onExpr, \" join \");\n        }\n\n        // Left Join\n        template <typename C>\n        inline auto LeftJoin (const C &,\n            const Expression::Expr &,\n            std::enable_if_t<\n            !HasInjected<C>::value>\n            * = nullptr) const\n        {}\n        template <typename C>\n        inline auto LeftJoin (const C &queryHelper2,\n            const Expression::Expr &onExpr,\n            std::enable_if_t<\n            HasInjected<C>::value>\n            * = nullptr) const\n        {\n            return _NewJoinQuery (queryHelper2, onExpr, \" left join \");\n        }\n\n        // Compound Select\n        inline Queryable Union (const Queryable &queryable) const\n        {\n            return _NewCompoundQuery (queryable, \" union \");\n        }\n        inline Queryable UnionAll (Queryable queryable) const\n        {\n            return _NewCompoundQuery (queryable, \" union all \");\n        }\n        inline Queryable Intersect (Queryable queryable) const\n        {\n            return _NewCompoundQuery (queryable, \" intersect \");\n        }\n        inline Queryable Except (Queryable queryable) const\n        {\n            return _NewCompoundQuery (queryable, \" excpet \");\n        }\n\n        // Get Result\n        template <typename T>\n        Nullable<T> Aggregate (const Expression::Aggregate<T> &agg) const\n        {\n            Nullable<T> ret;\n            _connector->ExecuteCallback (_sqlSelect + agg.fieldName +\n                _GetFromSql () + _GetLimit () + \";\",\n                [&] (int argc, char **argv)\n            {\n                if (argc != 1)\n                    throw std::runtime_error (BAD_COLUMN_COUNT);\n\n                BOT_ORM_Impl::DeserializationHelper::\n                    Deserialize (ret, argv[0]);\n            });\n            return ret;\n        }\n\n        std::vector<QueryResult> ToVector () const\n        {\n            std::vector<QueryResult> ret;\n            _Select (_queryHelper, ret);\n            return ret;\n        }\n        std::list<QueryResult> ToList () const\n        {\n            std::list<QueryResult> ret;\n            _Select (_queryHelper, ret);\n            return ret;\n        }\n\n    protected:\n        // Return FROM part for Query\n        inline std::string _GetFromSql () const\n        {\n            return _sqlFrom + _sqlWhere + _sqlGroupBy + _sqlHaving;\n        }\n\n        // Return ORDER BY & LIMIT part for Query\n        inline std::string _GetLimit () const\n        {\n            return _sqlOrderBy + _sqlLimit + _sqlOffset;\n        }\n\n        // Return a new Queryable Object\n        template <typename... Args>\n        inline Queryable<std::tuple<Args...>> _NewQuery (\n            std::string sqlTarget,\n            std::string sqlFrom,\n            std::tuple<Args...> &&newQueryHelper) const\n        {\n            return Queryable<std::tuple<Args...>> (\n                _connector, newQueryHelper,\n                std::move (sqlFrom),\n                _sqlSelect, std::move (sqlTarget),\n                _sqlWhere, _sqlGroupBy, _sqlHaving,\n                _sqlOrderBy, _sqlLimit, _sqlOffset);\n        }\n\n        // Return a new Join Queryable Object\n        template <typename C>\n        inline auto _NewJoinQuery (const C &queryHelper2,\n            const Expression::Expr &onExpr,\n            std::string joinStr) const\n        {\n            return _NewQuery (\n                _sqlTarget,\n                _sqlFrom + std::move (joinStr) +\n                BOT_ORM_Impl::InjectionHelper::TableName (queryHelper2) +\n                \" on \" + onExpr.ToString (),\n                BOT_ORM_Impl::QueryableHelper::JoinToTuple (\n                    _queryHelper, queryHelper2));\n        }\n\n        // Return a new Compound Queryable Object\n        Queryable _NewCompoundQuery (const Queryable &queryable,\n            std::string compoundStr) const\n        {\n            auto ret = *this;\n            ret._sqlFrom = ret._GetFromSql () +\n                std::move (compoundStr) +\n                queryable._sqlSelect + queryable._sqlTarget +\n                queryable._GetFromSql ();\n            ret._sqlWhere.clear ();\n            ret._sqlGroupBy.clear ();\n            ret._sqlHaving.clear ();\n            return ret;\n        }\n\n        // Select for Normal Objects\n        template <typename C, typename Out>\n        inline void _Select (const C &, Out &out) const\n        {\n            auto copy = _queryHelper;\n            _connector->ExecuteCallback (_sqlSelect + _sqlTarget +\n                _GetFromSql () + _GetLimit () + \";\",\n                [&] (int argc, char **argv)\n            {\n                BOT_ORM_Impl::InjectionHelper::Visit (\n                    copy, [argc] (auto & ... args)\n                {\n                    if (sizeof... (args) != argc)\n                        throw std::runtime_error (BAD_COLUMN_COUNT);\n                });\n\n                BOT_ORM_Impl::InjectionHelper::Visit (\n                    copy, [argv] (auto & ... args)\n                {\n                    size_t index = 0;\n                    (void) BOT_ORM_Impl::Expander\n                    {\n                        0, (BOT_ORM_Impl::DeserializationHelper::\n                            Deserialize (args, argv[index++]), 0)...\n                    };\n                });\n                out.push_back (copy);\n            });\n        }\n\n        // Select for Tuples\n        template <typename Out, typename... Args>\n        inline void _Select (const std::tuple<Args...> &, Out &out) const\n        {\n            auto copy = _queryHelper;\n            _connector->ExecuteCallback (_sqlSelect + _sqlTarget +\n                _GetFromSql () + _GetLimit () + \";\",\n                [&] (int argc, char **argv)\n            {\n                if (sizeof... (Args) != argc)\n                    throw std::runtime_error (BAD_COLUMN_COUNT);\n\n                size_t index = 0;\n                BOT_ORM_Impl::QueryableHelper::TupleVisit (\n                    copy, [argv, &index] (auto &val)\n                {\n                    BOT_ORM_Impl::DeserializationHelper::\n                        Deserialize (val, argv[index++]);\n                });\n                out.push_back (copy);\n            });\n        }\n    };\n\n    // ORMapper\n\n    class ORMapper\n    {\n        template <typename C>\n        using HasInjected =\n            BOT_ORM_Impl::InjectionHelper::HasInjected<C>;\n\n    public:\n        ORMapper (const std::string &connectionString)\n            : _connector (\n                std::make_shared<BOT_ORM_Impl::SQLConnector> (\n                    connectionString))\n        {\n            _connector->Execute (\"PRAGMA foreign_keys = ON;\");\n        }\n\n        template <typename Fn>\n        void Transaction (Fn fn)\n        {\n            try\n            {\n                _connector->Execute (\"begin transaction;\");\n                fn ();\n                _connector->Execute (\"commit transaction;\");\n            }\n            catch (...)\n            {\n                _connector->Execute (\"rollback transaction;\");\n                throw;\n            }\n        }\n\n        template <typename C, typename... Args>\n        std::enable_if_t<!HasInjected<C>::value>\n            CreateTbl (const C &, const Args & ...)\n        {}\n        template <typename C, typename... Args>\n        std::enable_if_t<HasInjected<C>::value>\n            CreateTbl (const C &entity,\n                const Args & ... constraints)\n        {\n            const auto &fieldNames =\n                BOT_ORM_Impl::InjectionHelper::FieldNames (entity);\n            std::unordered_map<std::string, std::string> fieldFixes;\n\n            auto addTypeStr = [&fieldNames, &fieldFixes] (\n                const auto &arg, size_t index)\n            {\n                // Why addTypeStr?\n                // Walkaround the 'undefined reference' in gcc/clang\n                constexpr const char *typeStr = BOT_ORM_Impl::TypeString<\n                    std::remove_cv_t<std::remove_reference_t<decltype(arg)>>\n                >::typeStr;\n                fieldFixes.emplace (fieldNames[index], typeStr);\n            };\n            (void) addTypeStr;\n\n            BOT_ORM_Impl::InjectionHelper::Visit (\n                entity, [&addTypeStr] (const auto & ... args)\n            {\n                size_t index = 0;\n                (void) BOT_ORM_Impl::Expander\n                {\n                    0, (addTypeStr (args, index++), 0)...\n                };\n            });\n            fieldFixes[fieldNames[0]] += \" primary key\";\n\n            std::string tableFixes;\n            _GetConstraints (tableFixes, fieldFixes, constraints...);\n\n            std::string strFmt;\n            for (const auto &field : fieldNames)\n                strFmt += field + fieldFixes[field] + \",\";\n            strFmt += std::move (tableFixes);\n            strFmt.pop_back ();\n\n            _connector->Execute (\n                \"create table \" +\n                BOT_ORM_Impl::InjectionHelper::TableName (entity) +\n                \"(\" + strFmt + \");\");\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            DropTbl (const C &)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            DropTbl (const C &entity)\n        {\n            _connector->Execute (\n                \"drop table \" +\n                BOT_ORM_Impl::InjectionHelper::TableName (entity) +\n                \";\");\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            Insert (const C &, bool = true)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            Insert (const C &entity, bool withId = true)\n        {\n            std::ostringstream os;\n            _GetInsert (os, entity, withId);\n            _connector->Execute (os.str ());\n        }\n\n        template <typename In, typename C = typename In::value_type>\n        std::enable_if_t<!HasInjected<C>::value>\n            InsertRange (const In &, bool = true)\n        {}\n        template <typename In, typename C = typename In::value_type>\n        std::enable_if_t<HasInjected<C>::value>\n            InsertRange (const In &entities, bool withId = true)\n        {\n            std::ostringstream os;\n            auto anyEntity = false;\n            for (const auto &entity : entities)\n            {\n                _GetInsert (os, entity, withId);\n                anyEntity = true;\n            }\n            if (anyEntity)\n                _connector->Execute (os.str ());\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            Update (const C &)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            Update (const C &entity)\n        {\n            std::ostringstream os;\n            if (_GetUpdate (os, entity))\n                _connector->Execute (os.str ());\n        }\n\n        template <typename In, typename C = typename In::value_type>\n        std::enable_if_t<!HasInjected<C>::value>\n            UpdateRange (const In &)\n        {}\n        template <typename In, typename C = typename In::value_type>\n        std::enable_if_t<HasInjected<C>::value>\n            UpdateRange (const In &entities)\n        {\n            std::ostringstream os, osTmp;\n            for (const auto &entity : entities)\n                if (_GetUpdate (osTmp, entity))\n                {\n                    os << osTmp.str ();\n                    osTmp.str (std::string {});  // Flush the previous data\n                }\n            auto sql = os.str ();\n            if (!sql.empty ()) _connector->Execute (sql);\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            Update (const C &,\n                const Expression::SetExpr &,\n                const Expression::Expr &)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            Update (const C &entity,\n                const Expression::SetExpr &setExpr,\n                const Expression::Expr &whereExpr)\n        {\n            _connector->Execute (\n                \"update \" +\n                BOT_ORM_Impl::InjectionHelper::TableName (entity) +\n                \" set \" + setExpr.ToString () +\n                \" where \" +\n                whereExpr.ToString () + \";\");\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            Delete (const C &)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            Delete (const C &entity)\n        {\n            const auto &fieldNames =\n                BOT_ORM_Impl::InjectionHelper::FieldNames (entity);\n\n            std::ostringstream os;\n            os << \"delete from \"\n                << BOT_ORM_Impl::InjectionHelper::TableName (entity)\n                << \" where \" << fieldNames[0] << \"=\";\n\n            // Primary Key\n            BOT_ORM_Impl::InjectionHelper::Visit (\n                entity, [&os] (const auto &primaryKey,\n                    const auto & ... dummy)\n            {\n                // Why 'eatdummy'?\n                // Walkaround 'fatal error c1001:\n                // an internal error has occurred in the compiler.' on MSVC 14\n                auto eatdummy = [] (const auto &) {};\n                (void) eatdummy;\n\n                // Why 'dummy'?\n                // Walkaround 'template argument deduction/substitution failed'\n                // on gcc 5.4\n                (void) BOT_ORM_Impl::Expander\n                {\n                    0, (eatdummy (dummy), 0)...\n                };\n\n                if (!BOT_ORM_Impl::SerializationHelper::\n                    Serialize (os, primaryKey))\n                    os << \"null\";\n            });\n            os << \";\";\n\n            _connector->Execute (os.str ());\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            Delete (const C &,\n                const Expression::Expr &)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            Delete (const C &entity,\n                const Expression::Expr &whereExpr)\n        {\n            _connector->Execute (\n                \"delete from \" +\n                BOT_ORM_Impl::InjectionHelper::TableName (entity) +\n                \" where \" +\n                whereExpr.ToString () + \";\");\n        }\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value, Queryable<C>>\n            Query (C)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value, Queryable<C>>\n            Query (C queryHelper)\n        {\n            return Queryable<C> (\n                _connector,\n                std::move (queryHelper),\n                std::string (\" from \") +\n                BOT_ORM_Impl::InjectionHelper::TableName (queryHelper));\n        }\n\n    protected:\n        std::shared_ptr<BOT_ORM_Impl::SQLConnector> _connector;\n\n        static void _GetConstraints (\n            std::string &,\n            std::unordered_map<std::string, std::string> &)\n        {}\n\n        template <typename... Args>\n        static void _GetConstraints (\n            std::string &tableFixes,\n            std::unordered_map<std::string, std::string> &fieldFixes,\n            const Constraint &constraint,\n            const Args & ... args)\n        {\n            if (!constraint.field.empty ())\n                fieldFixes[constraint.field] += constraint.constraint;\n            else\n                tableFixes += constraint.constraint + \",\";\n            _GetConstraints (tableFixes, fieldFixes, args...);\n        }\n\n        template <typename C>\n        static inline void _GetInsert (\n            std::ostream &os, const C &entity, bool withId)\n        {\n            BOT_ORM_Impl::InjectionHelper::Visit (\n                entity, [&os, &entity, withId] (\n                    const auto &primaryKey, const auto & ... args)\n            {\n                const auto &fieldNames =\n                    BOT_ORM_Impl::InjectionHelper::FieldNames (entity);\n\n                os << \"insert into \"\n                    << BOT_ORM_Impl::InjectionHelper::TableName (entity)\n                    << \"(\";\n\n                std::ostringstream osVal;\n\n                // Avoid Bad Eating of ,\n                bool anyField = false;\n\n                auto serializeField =\n                    [&fieldNames, &os, &osVal, &anyField] (\n                        const auto &val, size_t index)\n                {\n                    if (BOT_ORM_Impl::SerializationHelper::\n                        Serialize (osVal, val))\n                    {\n                        os << fieldNames[index] << \",\";\n                        osVal << \",\";\n                        anyField = true;\n                    }\n                };\n\n                // Priamry Key\n                if (withId &&\n                    BOT_ORM_Impl::SerializationHelper::\n                    Serialize (osVal, primaryKey))\n                {\n                    os << fieldNames[0] << \",\";\n                    osVal << \",\";\n                    anyField = true;\n                }\n\n                // The Rest\n                size_t index = 1;\n\n                (void) BOT_ORM_Impl::Expander\n                {\n                    0, (serializeField (args, index++), 0)...\n                };\n                (void) serializeField;\n\n                if (anyField)\n                {\n                    os.seekp (os.tellp () - std::streamoff (1));\n                    osVal.seekp (osVal.tellp () - std::streamoff (1));\n                }\n                else  // Fix for No Field for Insert...\n                {\n                    os << fieldNames[0];\n                    osVal << \"null\";\n                }\n\n                osVal << \");\";  // To Enable Seekp...\n                os << \") values (\" << osVal.str ();\n            });\n        }\n\n        template <typename C>\n        static inline bool _GetUpdate (\n            std::ostream &os, const C &entity)\n        {\n            return BOT_ORM_Impl::InjectionHelper::Visit (\n                entity, [&os, &entity] (\n                    const auto &primaryKey, const auto & ... args)\n            {\n                if (sizeof... (args) == 0)\n                    return false;\n\n                const auto &fieldNames =\n                    BOT_ORM_Impl::InjectionHelper::FieldNames (entity);\n                os << \"update \"\n                    << BOT_ORM_Impl::InjectionHelper::TableName (entity)\n                    << \" set \";\n\n                auto serializeField = [&fieldNames, &os] (\n                    const auto &val, size_t index)\n                {\n                    os << fieldNames[index] << \"=\";\n                    if (!BOT_ORM_Impl::SerializationHelper::\n                        Serialize (os, val))\n                        os << \"null\";\n                    os << \",\";\n                };\n\n                // The Rest\n                size_t index = 1;\n\n                (void) BOT_ORM_Impl::Expander\n                {\n                    0, (serializeField (args, index++), 0)...\n                };\n                (void) serializeField;\n\n                os.seekp (os.tellp () - std::streamoff (1));\n\n                // Primary Key\n                os << \" where \" << fieldNames[0] << \"=\";\n                if (!BOT_ORM_Impl::SerializationHelper::\n                    Serialize (os, primaryKey))\n                    os << \"null\";\n\n                os << \";\";\n                return true;\n            });\n        }\n    };\n\n    // Field Extractor\n\n    class FieldExtractor\n    {\n        using pair_type = std::pair<\n            const std::string &,\n            const std::string &>;\n\n        template <typename C>\n        using HasInjected =\n            BOT_ORM_Impl::InjectionHelper::HasInjected<C>;\n\n        template <typename C>\n        std::enable_if_t<!HasInjected<C>::value>\n            Extract (const C &)\n        {}\n        template <typename C>\n        std::enable_if_t<HasInjected<C>::value>\n            Extract (const C &helper)\n        {\n            BOT_ORM_Impl::InjectionHelper::Visit (\n                helper, [this, &helper] (\n                    const auto & ... args)\n            {\n                const auto &fieldNames =\n                    BOT_ORM_Impl::InjectionHelper::FieldNames (helper);\n                const auto &tableName =\n                    BOT_ORM_Impl::InjectionHelper::TableName (helper);\n\n                size_t index = 0;\n                (void) BOT_ORM_Impl::Expander\n                {\n                    0, (_map.emplace (\n                        (const void *) &args,\n                        pair_type { fieldNames[index++], tableName }\n                    ), 0)...\n                };\n            });\n        }\n\n    public:\n        template <typename... Classes>\n        FieldExtractor (const Classes & ... args)\n        {\n            (void) BOT_ORM_Impl::Expander\n            {\n                0, (Extract (args), 0)...\n            };\n        }\n\n        template <typename T>\n        inline Expression::Field<T> operator () (\n            const T &field) const\n        {\n            const auto &result = Get (field);\n            return Expression::Field<T> {\n                std::move (result.first), &result.second };\n        }\n\n        template <typename T>\n        inline Expression::NullableField<T> operator () (\n            const Nullable<T> &field) const\n        {\n            const auto &result = Get (field);\n            return Expression::NullableField<T> {\n                std::move (result.first), &result.second };\n        }\n\n    private:\n        std::unordered_map<const void *, pair_type> _map;\n\n        template <typename T>\n        const pair_type &Get (const T &field) const\n        {\n            try { return _map.at ((const void *) &field); }\n            catch (...) { throw std::runtime_error (NO_FIELD); }\n        }\n    };\n}\n\n// Clear Intra Macros\n#undef NO_ORMAP\n#undef BAD_TYPE\n\n#undef NO_FIELD\n#undef BAD_COLUMN_COUNT\n#undef NULL_DESERIALIZE\n#undef NOT_SAME_TABLE\n\n#endif // !BOT_ORM_H\n"
  },
  {
    "path": "test/makefile",
    "content": "\nTARGET = test\nSOURCES = test.cpp ../src/sqlite3.c\nWARNINGFLAGS = -Wall -W\nCPPFLAGS = -std=c++14\nLINKS = -lstdc++ -lpthread -ldl\n\nOBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))\n\n%.o: %.c\n\t$(CC) -c $< -o $@ $(WARNINGFLAGS) $(LINKS)\n\n%.o: %.cpp\n\t$(CC) -c $< -o $@ $(WARNINGFLAGS) $(LINKS) $(CPPFLAGS)\n\n$(TARGET): $(OBJS)\n\t$(CC) $(OBJS) -o $(TARGET) $(LINKS)\n\nclean:\n\trm -rf $(OBJS) $(TARGET) *.db\n"
  },
  {
    "path": "test/test.cpp",
    "content": "﻿\n// Test of ORM Lite\n// https://github.com/BOT-Man-JL/ORM-Lite\n// BOT Man, 2016\n\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include \"../src/ormlite.h\"\nusing namespace BOT_ORM;\nusing namespace BOT_ORM::Expression;\n\n#define CATCH_CONFIG_MAIN\n#include \"catch.hpp\"\n\n#define TESTDB \"test.db\"\n\nstruct ModelA\n{\n    int a_int;\n    std::string a_string;\n    double a_double;\n\n    Nullable<int> an_int;\n    Nullable<double> an_double;\n    Nullable<std::string> an_string;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"ModelA\", a_int, a_string, a_double, an_int, an_double, an_string);\n};\n\nstruct ModelB\n{\n    unsigned long b_ulong;\n    float b_float;\n\n    Nullable<unsigned long> bn_ulong;\n    Nullable<float> bn_float;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"ModelB\", b_ulong, b_float, bn_ulong, bn_float);\n};\n\nstruct ModelC\n{\n    unsigned c_uint;\n    int a_int;\n    unsigned long b_ulong;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"ModelC\", c_uint, a_int, b_ulong);\n};\n\nstruct ModelD\n{\n    int d_int;\n\n    // Inject ORM-Lite into this Class :-)\n    ORMAP (\"ModelD\", d_int);\n};\n\nnamespace detail\n{\n    template<typename Model>\n    void ResetTable (const Model &model)\n    {\n        ORMapper mapper (TESTDB);\n\n        try {\n            mapper.CreateTbl (model);\n        }\n        catch (...) {\n            mapper.DropTbl (model);\n            mapper.CreateTbl (model);\n        }\n    }\n}\n\nvoid ResetTables () {}\n\ntemplate<typename Model, typename ...OtherModels>\nvoid ResetTables (const Model &model, const OtherModels &...models)\n{\n    detail::ResetTable (model);\n    ResetTables (models...);\n}\n\nTEST_CASE (\"create/drop tables\")\n{\n    ResetTables (ModelA {}, ModelB {}, ModelC {}, ModelD {});\n\n    ORMapper mapper (TESTDB);\n\n    mapper.DropTbl (ModelA {});\n    mapper.DropTbl (ModelB {});\n    mapper.DropTbl (ModelC {});\n    mapper.DropTbl (ModelD {});\n\n    mapper.CreateTbl (ModelA {});\n    mapper.CreateTbl (ModelB {});\n    mapper.CreateTbl (ModelC {});\n    mapper.CreateTbl (ModelD {});\n}\n\nTEST_CASE (\"normal cases\")\n{\n    ModelA ma;\n    ModelD md;\n    auto field = FieldExtractor { ma, md };\n\n    ORMapper mapper (TESTDB);\n\n    mapper.Insert (ModelD { 0 });\n    mapper.Insert (ModelD { 0 }, false);\n    mapper.InsertRange (std::list<ModelD> { ModelD { 2 }, ModelD { 3 } });\n    mapper.InsertRange (std::list<ModelD> { ModelD { 2 }, ModelD { 3 } }, false);\n    mapper.Update (ModelD { 0 });\n    mapper.UpdateRange (std::list<ModelD> { ModelD { 2 }, ModelD { 3 } });\n    mapper.Update (ModelD {}, field (md.d_int) = 6, field (md.d_int) == 0);  // 0 -> 6\n    mapper.Delete (ModelD { 1 });\n    mapper.Delete (ModelD {}, field (md.d_int) == 0);  // No such one\n\n    constexpr auto countExpected = 5;\n    constexpr auto firstIdExpected = 2;\n    constexpr auto lastIdExpected = 6;\n    // Expected: 2, 3, 4, 5, 6\n\n    REQUIRE (mapper.Query (ModelD {})\n        .Aggregate (Count ()).Value () == countExpected);\n    REQUIRE (mapper.Query (ModelD {})\n        .LeftJoin (ModelA {}, field (ma.a_int) == field (md.d_int))\n        .Aggregate (Count ()).Value () == countExpected);\n\n    mapper.Insert (ModelA {}, false);\n    REQUIRE (mapper.Query (ModelD {}).Select (field (md.d_int))\n        .Union (mapper.Query (ModelA {}).Select (field (ma.a_int)))\n        .ToList ().size () == countExpected + 1);\n    REQUIRE (mapper.Query (ModelD {})\n        .ToVector ()[countExpected - 1].d_int == lastIdExpected);\n    auto firstTuple = mapper.Query (ModelD {})\n        .Select (field (md.d_int))\n        .ToList ().front ();\n    REQUIRE (std::get<0> (firstTuple).Value () == firstIdExpected);\n}\n\nTEST_CASE (\"handle existing table\")\n{\n    // before\n    ResetTables (ModelD {});\n    {\n        sqlite3 *db;\n        sqlite3_open (TESTDB, &db);\n        sqlite3_exec (db,\n            \"DROP TABLE ModelD;\"\n            \"CREATE TABLE ModelD (d_int INTEGER, d_str TEXT);\"\n            \"INSERT INTO ModelD values (1, 'John');\",\n            nullptr, nullptr, nullptr);\n        sqlite3_close (db);\n    }\n\n    // test\n    ORMapper mapper (TESTDB);\n    REQUIRE_THROWS_WITH (mapper.Query (ModelD {}).ToList (),\n        \"SQL error: 'Bad Column Count' at 'select * from ModelD;'\");\n}\n\nTEST_CASE (\"chinese characters\")\n{\n    // before\n    ResetTables (ModelA {});\n\n    // test\n    ORMapper mapper (TESTDB);\n\n    mapper.Insert (\n        ModelA { 0, \"你好\", 0, nullptr, nullptr, nullptr }, false);\n    mapper.Insert (\n        ModelA { 0, u8\"世界\", 0, nullptr, nullptr, nullptr }, false);\n\n    auto chinese = mapper.Query (ModelA {}).ToVector ();\n\n    REQUIRE (chinese.size () == 2);\n    REQUIRE (chinese[0].a_string == \"你好\");\n    REQUIRE (chinese[1].a_string == u8\"世界\");\n}\n\nTEST_CASE (\"lifetime of mapper\")\n{\n    // before\n    ResetTables (ModelA {});\n    {\n        ORMapper mapper (TESTDB);\n        mapper.Insert (ModelA {}, false);\n        mapper.Insert (ModelA {}, false);\n    }\n\n    // test\n    std::unique_ptr<Queryable<ModelA>> queryable;\n    {\n        ORMapper mapper (TESTDB);\n        queryable.reset (new Queryable<ModelA> { mapper.Query (ModelA {}) });\n    }\n    REQUIRE (queryable->ToList ().size () == 2);\n}\n\nusing InvalidModel = int;\n\nTEST_CASE (\"invalid model\", \"[not-compile]\")\n{\n    ORMapper mapper (TESTDB);\n\n    //mapper.CreateTbl (InvalidModel {});\n    //mapper.CreateTbl (InvalidModel {}, Constraint::Unique (Field<int> {\"\", nullptr}));\n    //mapper.DropTbl (InvalidModel {});\n\n    //mapper.Insert (InvalidModel {});\n    //mapper.Insert (InvalidModel {}, false);\n    ////mapper.InsertRange (InvalidModel {});\n    //mapper.InsertRange (std::vector<int> {});\n    //mapper.InsertRange (std::vector<int> {}, false);\n    //mapper.Update (InvalidModel {});\n    ////mapper.UpdateRange (InvalidModel {});\n    //mapper.UpdateRange (std::vector<int> {});\n    //mapper.Update (InvalidModel {}, SetExpr { \"\" }, Expr { Selectable<int> {\"\", nullptr}, \"\" });\n    //mapper.Delete (InvalidModel {});\n    //mapper.Delete (InvalidModel {}, Expr { Selectable<int> {\"\", nullptr}, \"\" });\n\n    //mapper.Query (InvalidModel {});\n    //FieldExtractor { InvalidModel {}, double () };\n    ////mapper.Query (ModelA {})\n    ////\t.Join (InvalidModel {}, Expr { Selectable<int> {\"\", nullptr}, \"\" });\n    ////mapper.Query (ModelA {})\n    ////\t.LeftJoin (InvalidModel {}, Expr { Selectable<int> {\"\", nullptr}, \"\" });\n}\n\nstruct SickModel\n{\n    ModelD dd;\n    char ch;\n    ORMAP (\"SickModel\", dd, ch);\n};\n\nTEST_CASE (\"invalid field\", \"[not-compile]\")\n{\n    ORMapper mapper (TESTDB);\n\n    //mapper.CreateTbl (SickModel {});\n    //mapper.Insert (SickModel {});\n    //mapper.Update (SickModel {});\n    //mapper.Delete (SickModel {});\n    //mapper.Query (SickModel {}).ToList ();\n}\n"
  },
  {
    "path": "test/test.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1781A74F1F5FED13008E6067 /* test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1781A74E1F5FED13008E6067 /* test.cpp */; };\n\t\t1781A7531F5FEDB3008E6067 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 1781A7511F5FEDB3008E6067 /* sqlite3.c */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t1781A7421F5FECD1008E6067 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1781A7441F5FECD1008E6067 /* test */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = test; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t1781A74E1F5FED13008E6067 /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test.cpp; sourceTree = \"<group>\"; };\n\t\t1781A7541F5FEE5D008E6067 /* nullable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nullable.h; path = ../src/nullable.h; sourceTree = \"<group>\"; };\n\t\t1781A7501F5FED8A008E6067 /* ormlite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ormlite.h; path = ../src/ormlite.h; sourceTree = \"<group>\"; };\n\t\t1781A7511F5FEDB3008E6067 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = ../src/sqlite3.c; sourceTree = \"<group>\"; };\n\t\t1781A7521F5FEDB3008E6067 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = ../src/sqlite3.h; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t1781A7411F5FECD1008E6067 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t1781A73B1F5FECD1008E6067 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1781A7541F5FEE5D008E6067 /* nullable.h */,\n\t\t\t\t1781A7501F5FED8A008E6067 /* ormlite.h */,\n\t\t\t\t1781A7511F5FEDB3008E6067 /* sqlite3.c */,\n\t\t\t\t1781A7521F5FEDB3008E6067 /* sqlite3.h */,\n\t\t\t\t1781A74E1F5FED13008E6067 /* test.cpp */,\n\t\t\t\t1781A7451F5FECD1008E6067 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1781A7451F5FECD1008E6067 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1781A7441F5FECD1008E6067 /* test */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t1781A7431F5FECD1008E6067 /* test */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1781A74B1F5FECD1008E6067 /* Build configuration list for PBXNativeTarget \"test\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t1781A7401F5FECD1008E6067 /* Sources */,\n\t\t\t\t1781A7411F5FECD1008E6067 /* Frameworks */,\n\t\t\t\t1781A7421F5FECD1008E6067 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = test;\n\t\t\tproductName = test;\n\t\t\tproductReference = 1781A7441F5FECD1008E6067 /* test */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t1781A73C1F5FECD1008E6067 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0830;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t1781A7431F5FECD1008E6067 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.3.3;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 1781A73F1F5FECD1008E6067 /* Build configuration list for PBXProject \"test\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 1781A73B1F5FECD1008E6067;\n\t\t\tproductRefGroup = 1781A7451F5FECD1008E6067 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t1781A7431F5FECD1008E6067 /* test */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t1781A7401F5FECD1008E6067 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t1781A74F1F5FED13008E6067 /* test.cpp in Sources */,\n\t\t\t\t1781A7531F5FEDB3008E6067 /* sqlite3.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1781A7491F5FECD1008E6067 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1781A74A1F5FECD1008E6067 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1781A74C1F5FECD1008E6067 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1781A74D1F5FECD1008E6067 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1781A73F1F5FECD1008E6067 /* Build configuration list for PBXProject \"test\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1781A7491F5FECD1008E6067 /* Debug */,\n\t\t\t\t1781A74A1F5FECD1008E6067 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1781A74B1F5FECD1008E6067 /* Build configuration list for PBXNativeTarget \"test\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1781A74C1F5FECD1008E6067 /* Debug */,\n\t\t\t\t1781A74D1F5FECD1008E6067 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 1781A73C1F5FECD1008E6067 /* Project object */;\n}\n"
  },
  {
    "path": "test/test.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{AD41C840-0ADD-43E1-BF17-60EC79CEEEFC}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>test</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>$(SolutionDir)$(Configuration)\\test\\</OutDir>\n    <IntDir>$(Configuration)\\test\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IntDir>$(Platform)\\$(Configuration)\\test\\</IntDir>\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\test\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\src\\sqlite3.c\" />\n    <ClCompile Include=\"test.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\src\\ormlite.h\" />\n    <ClInclude Include=\"..\\src\\nullable.h\" />\n    <ClInclude Include=\"..\\src\\sqlite3.h\" />\n    <ClInclude Include=\"catch.hpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  }
]