Skip to content

LomanTrue/Database

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SimpleSqlDB — реляционная in-memory (с возможностью хранения в файле) БД на C++ с поддержкой SQL

Реализация реляционной СУБД на C++17 без внешних зависимостей в runtime-коде. Парсит подмножество SQL, выполняет запросы над таблицами в памяти, умеет сохранять и загружать состояние БД в файл. Реализована в виде статической библиотеки с публичным классом SimpleSqlDB.

Возможности

  • DDL: CREATE TABLE, DROP TABLE с поддержкой PRIMARY KEY
  • DML: INSERT INTO ... VALUES, UPDATE ... SET, DELETE FROM
  • Запросы: SELECT с фильтрацией WHERE, логическими операторами AND / OR / NOT, проверкой IS NULL / IS NOT NULL
  • Соединения: INNER JOIN, LEFT JOIN, RIGHT JOIN для двух таблиц по условию ON
  • Типы данных: BOOL, INT, FLOAT, DOUBLE, VARCHAR(N)
  • Сериализация: сохранение и загрузка состояния БД в файл
  • Результат любого запроса возвращается строкой и может быть выведен в любой поток

Ограничения

  • Вложенные подзапросы не поддерживаются
  • JOIN работает только между двумя таблицами
  • FOREIGN KEY пока не реализован

Пример использования библиотеки

#include <iostream>
#include "SimpleSqlDB.h"

int main() {
    SimpleSqlDB db;

    std::string create  = "CREATE TABLE orders (id INT PRIMARY KEY);";
    std::string insert  = "INSERT INTO orders (id) VALUES (1), (2), (3);";
    std::string select  = "SELECT * FROM orders WHERE id > 1;";

    std::cout << db.Execute(create);
    std::cout << db.Execute(insert);
    std::cout << db.Execute(select);
}

В строку Execute можно передать несколько запросов, разделённых ;. Результат выполнения возвращается строкой — её можно вывести, записать в файл, отправить по сети.

Пример SQL-скрипта

Файл config.txt:

CREATE TABLE orders (id INT PRIMARY KEY, order_number VARCHAR(10), customer_id INT, a BOOL);

INSERT INTO orders (id, order_number, customer_id, a)
VALUES (1, 'ORD001', 101, TRUE),
       (2, 'ORD002', 102, FALSE),
       (3, 'ORD003', 101, FALSE);

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100));

INSERT INTO customers (id, name, email)
VALUES (101, 'Dima',  'dima.com'),
       (102, 'Egor',  'egor.com'),
       (11,  'Dima',  'dima2.com'),
       (103, 'Igor',  'igor.com');

SELECT * FROM orders
RIGHT JOIN customers ON customers.id = orders.customer_id;

Поддерживаемый синтаксис

Категория Ключевые слова
DDL CREATE TABLE, DROP TABLE, PRIMARY KEY
DML INSERT, INTO, VALUES, UPDATE, DELETE, FROM
Запросы SELECT, WHERE, ON
Соединения INNER JOIN, LEFT JOIN, RIGHT JOIN
Логика AND, OR, NOT, IS, NULL
Типы BOOL, INT, FLOAT, DOUBLE, VARCHAR(N)

Архитектура

Проект разделён на несколько модулей, каждый из которых собирается как отдельная статическая библиотека:

Database/
├── main.cpp              # Демо-приложение
├── lib/
│   ├── SimpleSqlDB.{h,cpp}  # Фасад БД: Execute, сериализация, парсинг
│   ├── Table.{h,cpp}        # Таблица: хранение строк, операции над данными
│   ├── Column.{h,cpp}       # Колонка: имя, тип, ограничения
│   ├── Request.{h,cpp}      # Распарсенный запрос: тип, операнды, условия
│   ├── ParseFile.cpp        # Считывает SQL-запрос с конфига
│   └── CMakeLists.txt
├── tests/
│   ├── tests.cpp            # Тесты на GoogleTest
│   └── CMakeLists.txt
├── config.txt               # Пример SQL-скрипта
└── CMakeLists.txt

Публичный API (lib/SimpleSqlDB.h):

class SimpleSqlDB {
public:
    std::string Execute(const std::string& req_str);
private:
    std::vector<Table> tables;
    int WriteFile(std::filesystem::path file_name);
    int ReadFile(std::filesystem::path file_name);
    int Parse(std::vector<std::string>& data, int* i, std::string& res);
};

API намеренно минималистичен: на вход — строка с SQL, на выход — строка с результатом. Это делает интеграцию SimpleSqlDB с любым приложением тривиальной.

Стек

  • C++17
  • CMake ≥ 3.23
  • STL (<vector>, <filesystem>, <fstream>, …)
  • GoogleTest 1.12.1 — только для тестов, подтягивается через FetchContent

В runtime-коде библиотеки внешних зависимостей нет.

Сборка и запуск

git clone https://github.com/LomanTrue/Database.git
cd Database
mkdir build && cd build
cmake ..
cmake --build .

После сборки в build/ появится исполняемый файл SimpleDatabase — демо-приложение из main.cpp.

Тесты

Тесты написаны на GoogleTest и подтягиваются автоматически при сборке через FetchContent. Покрытие — основные сценарии работы с таблицами и SQL-запросами.

Пример теста:

TEST(DBTest, WriteAndReadIntoFileOneTable) {
  SimpleSqlDB x;
  std::string req1 = "CREATE TABLE orders (id INT PRIMARY KEY,\n"
                    "    order_number VARCHAR(10),\n"
                    "    customer_id INT, a BOOL); INSERT INTO orders (id, order_number, customer_id, a) VALUES\n"
                    "    (1, 'ORD001', 101, TRUE),\n"
                    "    (2, 'ORD002', 102, FALSE),\n"
                    "    (3, 'ORD003', 101, FALSE);\n"
                    "WRITE '1.txt';";

  SimpleSqlDB y;
  std::string req2 = "READ '1.txt'; "
                     "SELECT * FROM orders;";

  ASSERT_EQ(x.Execute(req1), "Table \"orders\" created\nData inserted\nDatabase wrote into a file \"1.txt\"\n");
  ASSERT_EQ(y.Execute(req2), "Database read from file \"1.txt\"\n1 ORD001 101 TRUE \n2 ORD002 102 FALSE \n3 ORD003 101 FALSE \n\n");
}

Запуск тестов

cd build
ctest --output-on-failure

или напрямую исполняемым файлом:

./tests/db_tests          # Linux / macOS
tests\db_tests.exe        # Windows

About

Relational in-memory (save/write in file) database with SQL support (SELECT, JOIN, WHERE, CREATE/DROP TABLE) and state serialization. C++17, GoogleTest, no runtime dependencies.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages