README.md

Arctic SQL

SQL mapping library for C++ offering a simple, light, fast, and type-safe layer between your POCOs and your database.

The library suggests an interface one step above micro-ORMs thus keeping a thin abstraction layer between your code and the database. Your queries are checked by the C++ compiler and allow for easy refactoring. However, it’s not as heavy as Hibernate or Entity Framework. I would say that the most close analogue is Linkq2db in C#.

Dependencies

The foundation for Arctic SQL is a wonderfull cppparser library. This allowes us to keep consice POCO classes and translate them transparently so that they can be used in complex queries.

Boost is also used to generate uuids and work with files.

SQLite3 and Postgres packages are required as well. Currently no other database engines are supported.

Example

Connecting to database

SQLite

#include <arctic/sql/sql.hpp>
#include <arctic/sql/sqlite/sqlite.hpp>
auto sqlite_connptr = sqlite::SQLiteConnector::Connect(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
auto connptr = std::dynamic_pointer_cast<IConnector>(sqlite_connptr);

:memory: - can be replaced with file path.

Postgres

#include <arctic/sql/sql.hpp>
#include <arctic/sql/postgres/postgres.hpp>
auto postgres_connptr = postgres::PostgresConnector::Connect("postgresql://postgres:<password>@localhost/<database>");
auto connptr = std::dynamic_pointer_cast<IConnector>(postgres_connptr);

Define POCO class

class [[Table]] Department {
public:
    [[PK]] [[NotNull]]
    Int CompanyID;

    [[PK]] [[AutoIncrement]] [[NotNull]]
    Int DepartmentID;

    Text Name;
};

struct [[Table]] Person {
    [[PK]] [[NotNull]]
    Int CompanyID;

    [[PK]] [[AutoIncrement]] [[NotNull]] 
    Int PersonID;

    [[DBName("DepartmentID")]]
    Int DeptID;

    Text LastName;
    Text FirstName;
    Text Phone;
    Text Email;

    Long ExternalID;
    Double Balance;
    Bool Fired;
    Date Birthdate;
    DateTime LastLoginTime;
    TimeDuration WorkDayDuration;
};

Selecting data

Department dept;
Person person;
auto query = 
    Select()
    .From(person)
        .LeftJoin(dept).On(dept->DepartmentID == person->DeptID)
    .Where(!person->Fired)
    .Offset(20).FetchFirst(10);
auto data = connptr->Exec(query);
while (auto rec = data->FetchRecord()) {
    std::cout << "#" << person.PersonID
        << " " << person.FirstName
        << " " << person.LastName
        << " <" << person.Email << ">"
        << std::endl;
}

Certain columns can be selected using expressions, aggregations and even subqueries.

auto query = 
    Select(person->PersonID
        , Case()
            .When(person->LastName == "Иванов").Then(Literal("Иван"))
            .When(person->LastName == "Petrov").Then(person->FirstName)
            .Else(person->Email)
            .As("CaseExpr")
        , person->Balance
        , (person->Balance == Select(person->Balance.Max()).From(person))->As("MaxBalance"))
    .From(person);

While there is still no proper documentation please find the examples in tests: sql-expr-test.cpp, postgres-test.cpp and others.

Changing data

Insert

Person p1;
p1.CompanyID = 1;
p1.LastName = "Petrov";
p1.FirstName = "Petr";
p1.Phone = "+7 (916) 222-22-22";
p1.Email = "petr.petrov@example.com";

connptr->Exec(Insert(p1));

Update

Person person;
auto selectIvanov = Select().From(person).Where(person->PersonID == 2);
auto data = connptr->Exec(selectIvanov);
auto rec = data->FetchRecord();
Person ivanov = rec[person];

ivanov.Phone = "+7 (985) 111-11-11";
auto updateExpr = Update(ivanov);
connptr->Exec(updateExpr);

Delete

Person person;
auto query = Select().From(person).Where(person->PersonID == 2);
auto data = connptr->Exec(query);
auto rec = data->FetchRecord();

connptr->Exec(Delete(person));

Building

Build: Windows (MSVC)

Make and install cppparser

cd ~/thirdparty
git clone https://github.com/satya-das/common.git
git clone https://github.com/satya-das/cppparser.git
cd cppparser
cmake -B build -S .
cmake --build build --config Debug
cmake --build build --config Debug --target install

Install vcpkg to fetch boost

cd <arctic-sql project dir>
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="[path to vcpkg]/scripts/buildsystems/vcpkg.cmake"
cmake --build build --config Debug
.\build\bin\Debug\sql-test.exe
cmake --build build --config Debug --target install

Build: Ubuntu (22.04)

sudo apt update
sudo apt install git cmake g++ libboost-all-dev flex libsqlite3-dev zlib1g-dev
#sudo pip install conan

cd ~/thirdparty
git clone https://github.com/satya-das/common.git
git clone https://github.com/satya-das/cppparser.git
cd cppparser
mkdir build && cd build
cmake ..
make
sudo make install

cd <arctic-sql project dir>
mkdir build && cd build
cmake ..
make
./test/sql-test
./test/pg-test
sudo make install
Конвейеры
0 успешных
0 с ошибкой