mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:58:11 +00:00
LibSQL: Database layer
This patch implements the beginnings of a database API allowing for the creation of tables, inserting rows in those tables, and retrieving those rows.
This commit is contained in:
parent
267eb3b329
commit
87bd69559f
7 changed files with 511 additions and 0 deletions
188
Tests/LibSQL/TestSqlDatabase.cpp
Normal file
188
Tests/LibSQL/TestSqlDatabase.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <LibSQL/BTree.h>
|
||||
#include <LibSQL/Database.h>
|
||||
#include <LibSQL/Heap.h>
|
||||
#include <LibSQL/Meta.h>
|
||||
#include <LibSQL/Row.h>
|
||||
#include <LibSQL/Value.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
NonnullRefPtr<SQL::SchemaDef> setup_schema(SQL::Database&);
|
||||
NonnullRefPtr<SQL::SchemaDef> setup_table(SQL::Database&);
|
||||
void insert_into_table(SQL::Database&, int);
|
||||
void verify_table_contents(SQL::Database&, int);
|
||||
void insert_and_verify(int);
|
||||
|
||||
NonnullRefPtr<SQL::SchemaDef> setup_schema(SQL::Database& db)
|
||||
{
|
||||
auto schema = SQL::SchemaDef::construct("TestSchema");
|
||||
EXPECT(schema != nullptr);
|
||||
db.add_schema(schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
NonnullRefPtr<SQL::SchemaDef> setup_table(SQL::Database& db)
|
||||
{
|
||||
auto schema = setup_schema(db);
|
||||
auto table = SQL::TableDef::construct(schema, "TestTable");
|
||||
EXPECT(table != nullptr);
|
||||
db.add_table(table);
|
||||
table->append_column("TextColumn", SQL::SQLType::Text);
|
||||
table->append_column("IntColumn", SQL::SQLType::Integer);
|
||||
EXPECT_EQ(table->num_columns(), 2u);
|
||||
db.add_table(table);
|
||||
return table;
|
||||
}
|
||||
|
||||
void insert_into_table(SQL::Database& db, int count)
|
||||
{
|
||||
auto table = db.get_table("TestSchema", "TestTable");
|
||||
EXPECT(table);
|
||||
|
||||
for (int ix = 0; ix < count; ix++) {
|
||||
SQL::Row row(*table);
|
||||
StringBuilder builder;
|
||||
builder.appendff("Test{}", ix);
|
||||
|
||||
row["TextColumn"] = builder.build();
|
||||
row["IntColumn"] = ix;
|
||||
EXPECT(db.insert(row));
|
||||
}
|
||||
}
|
||||
|
||||
void verify_table_contents(SQL::Database& db, int expected_count)
|
||||
{
|
||||
auto table = db.get_table("TestSchema", "TestTable");
|
||||
EXPECT(table);
|
||||
|
||||
int sum = 0;
|
||||
int count = 0;
|
||||
for (auto& row : db.select_all(*table)) {
|
||||
StringBuilder builder;
|
||||
builder.appendff("Test{}", row["IntColumn"].to_int().value());
|
||||
EXPECT_EQ(row["TextColumn"].to_string().value(), builder.build());
|
||||
count++;
|
||||
sum += row["IntColumn"].to_int().value();
|
||||
}
|
||||
EXPECT_EQ(count, expected_count);
|
||||
EXPECT_EQ(sum, (expected_count * (expected_count - 1)) / 2);
|
||||
}
|
||||
|
||||
void insert_and_verify(int count)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
setup_table(db);
|
||||
db->commit();
|
||||
}
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
insert_into_table(db, count);
|
||||
db->commit();
|
||||
}
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
verify_table_contents(db, count);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(create_heap)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
auto heap = SQL::Heap::construct("test.db");
|
||||
EXPECT_EQ(heap->version(), 0x00000001u);
|
||||
}
|
||||
|
||||
TEST_CASE(create_database)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
db->commit();
|
||||
}
|
||||
|
||||
TEST_CASE(add_schema_to_database)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
setup_schema(db);
|
||||
db->commit();
|
||||
}
|
||||
|
||||
TEST_CASE(get_schema_from_database)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
setup_schema(db);
|
||||
db->commit();
|
||||
}
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
auto schema = db->get_schema("TestSchema");
|
||||
EXPECT(schema);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(add_table_to_database)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
setup_table(db);
|
||||
db->commit();
|
||||
}
|
||||
|
||||
TEST_CASE(get_table_from_database)
|
||||
{
|
||||
ScopeGuard guard([]() { unlink("test.db"); });
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
setup_table(db);
|
||||
db->commit();
|
||||
}
|
||||
{
|
||||
auto db = SQL::Database::construct("test.db");
|
||||
auto table = db->get_table("TestSchema", "TestTable");
|
||||
EXPECT(table);
|
||||
EXPECT_EQ(table->name(), "TestTable");
|
||||
EXPECT_EQ(table->num_columns(), 2u);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(insert_one_into_and_select_from_table)
|
||||
{
|
||||
insert_and_verify(1);
|
||||
}
|
||||
|
||||
TEST_CASE(insert_two_into_table)
|
||||
{
|
||||
insert_and_verify(2);
|
||||
}
|
||||
|
||||
TEST_CASE(insert_10_into_table)
|
||||
{
|
||||
insert_and_verify(10);
|
||||
}
|
||||
|
||||
TEST_CASE(insert_100_into_table)
|
||||
{
|
||||
insert_and_verify(100);
|
||||
}
|
||||
|
||||
TEST_CASE(insert_1000_into_table)
|
||||
{
|
||||
insert_and_verify(1000);
|
||||
}
|
||||
|
||||
TEST_CASE(insert_10000_into_table)
|
||||
{
|
||||
insert_and_verify(10000);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue