Skip to content

Commit

Permalink
Extend QueryBuilder API to table schema modification queries and make…
Browse files Browse the repository at this point in the history
… use of it in unit tests

Signed-off-by: Christian Parpart <[email protected]>
  • Loading branch information
christianparpart committed Dec 2, 2024
1 parent 2733fdd commit 0af1dc4
Show file tree
Hide file tree
Showing 15 changed files with 1,183 additions and 95 deletions.
4 changes: 4 additions & 0 deletions src/Lightweight/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ set(HEADER_FILES
SqlQuery/Core.hpp
SqlQuery/Delete.hpp
SqlQuery/Insert.hpp
SqlQuery/Migrate.hpp
SqlQuery/MigrationPlan.hpp
SqlQuery/Select.hpp
SqlQuery/Update.hpp

Expand Down Expand Up @@ -70,6 +72,8 @@ set(SOURCE_FILES
SqlError.cpp
SqlLogger.cpp
SqlQuery.cpp
SqlQuery/Migrate.cpp
SqlQuery/MigrationPlan.cpp
SqlQuery/Select.cpp
SqlQueryFormatter.cpp
SqlSchema.cpp
Expand Down
5 changes: 5 additions & 0 deletions src/Lightweight/SqlConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,8 @@ SqlQueryBuilder SqlConnection::QueryAs(std::string_view const& table, std::strin
{
return SqlQueryBuilder(QueryFormatter(), std::string(table), std::string(tableAlias));
}

SqlMigrationQueryBuilder SqlConnection::Migration() const
{
return SqlMigrationQueryBuilder(QueryFormatter());
}
8 changes: 6 additions & 2 deletions src/Lightweight/SqlConnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <sqltypes.h>

class SqlQueryBuilder;
class SqlMigrationQueryBuilder;
class SqlQueryFormatter;

// @brief Represents a connection to a SQL database.
Expand Down Expand Up @@ -108,12 +109,15 @@ class LIGHTWEIGHT_API SqlConnection final
// Retrieves a query formatter suitable for the SQL server being connected.
[[nodiscard]] SqlQueryFormatter const& QueryFormatter() const noexcept;

// Creates a new query builder for the given table, compatible with the SQL server being connected.
// Creates a new query builder for the given table, compatible with the current connection.
[[nodiscard]] SqlQueryBuilder Query(std::string_view const& table = {}) const;

// Creates a new query builder for the given table with an alias, compatible with the SQL server being connected.
// Creates a new query builder for the given table with an alias, compatible with the current connection.
[[nodiscard]] SqlQueryBuilder QueryAs(std::string_view const& table, std::string_view const& tableAlias) const;

// Creates a new migration query builder, compatible the current connection.
[[nodiscard]] SqlMigrationQueryBuilder Migration() const;

// Retrieves the SQL traits for the server.
[[nodiscard]] SqlTraits const& Traits() const noexcept
{
Expand Down
5 changes: 5 additions & 0 deletions src/Lightweight/SqlQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ SqlDeleteQueryBuilder SqlQueryBuilder::Delete() noexcept
{
return SqlDeleteQueryBuilder(m_formatter, std::move(m_table), std::move(m_tableAlias));
}

LIGHTWEIGHT_API SqlMigrationQueryBuilder SqlQueryBuilder::Migration()
{
return SqlMigrationQueryBuilder(m_formatter);
}
3 changes: 3 additions & 0 deletions src/Lightweight/SqlQuery.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Api.hpp"
#include "SqlQuery/Delete.hpp"
#include "SqlQuery/Insert.hpp"
#include "SqlQuery/Migrate.hpp"
#include "SqlQuery/Select.hpp"
#include "SqlQuery/Update.hpp"

Expand Down Expand Up @@ -42,6 +43,8 @@ class [[nodiscard]] SqlQueryBuilder final
// Initiates DELETE query building
LIGHTWEIGHT_API SqlDeleteQueryBuilder Delete() noexcept;

LIGHTWEIGHT_API SqlMigrationQueryBuilder Migration();

private:
SqlQueryFormatter const& m_formatter;
std::string m_table;
Expand Down
167 changes: 167 additions & 0 deletions src/Lightweight/SqlQuery/Migrate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// SPDX-License-Identifier: Apache-2.0

#include "../SqlQueryFormatter.hpp"
#include "Migrate.hpp"

SqlMigrationPlan SqlMigrationQueryBuilder::GetPlan()
{
return _migrationPlan;
}

SqlMigrationQueryBuilder& SqlMigrationQueryBuilder::DropTable(std::string_view tableName)
{
_migrationPlan.steps.emplace_back(SqlDropTablePlan {
.tableName = tableName,
});
return *this;
}

SqlCreateTableQueryBuilder SqlMigrationQueryBuilder::CreateTable(std::string_view tableName)
{
_migrationPlan.steps.emplace_back(SqlCreateTablePlan {
.tableName = tableName,
.columns = {},
});
return SqlCreateTableQueryBuilder { std::get<SqlCreateTablePlan>(_migrationPlan.steps.back()) };
}

SqlAlterTableQueryBuilder SqlMigrationQueryBuilder::AlterTable(std::string_view tableName)
{
_migrationPlan.steps.emplace_back(SqlAlterTablePlan {
.tableName = tableName,
.commands = {},
});
return SqlAlterTableQueryBuilder { std::get<SqlAlterTablePlan>(_migrationPlan.steps.back()) };
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::RenameTo(std::string_view newTableName)
{
_plan.commands.emplace_back(SqlAlterTableCommands::RenameTable {
.newTableName = newTableName,
});
return *this;
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::AddColumn(std::string_view columnName,
SqlColumnTypeDefinition columnType)
{
_plan.commands.emplace_back(SqlAlterTableCommands::AddColumn {
.columnName = columnName,
.columnType = columnType,
});
return *this;
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::RenameColumn(std::string_view oldColumnName,
std::string_view newColumnName)
{
_plan.commands.emplace_back(SqlAlterTableCommands::RenameColumn {
.oldColumnName = oldColumnName,
.newColumnName = newColumnName,
});
return *this;
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::DropColumn(std::string_view columnName)
{
_plan.commands.emplace_back(SqlAlterTableCommands::DropColumn {
.columnName = columnName,
});
return *this;
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::AddIndex(std::string_view columnName)
{
_plan.commands.emplace_back(SqlAlterTableCommands::AddIndex {
.columnName = columnName,
.unique = false,
});
return *this;
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::AddUniqueIndex(std::string_view columnName)
{
_plan.commands.emplace_back(SqlAlterTableCommands::AddIndex {
.columnName = columnName,
.unique = true,
});
return *this;
}

SqlAlterTableQueryBuilder& SqlAlterTableQueryBuilder::DropIndex(std::string_view columnName)
{
_plan.commands.emplace_back(SqlAlterTableCommands::DropIndex {
.columnName = columnName,
});
return *this;
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::Column(SqlColumnDeclaration column)
{
_plan.columns.emplace_back(std::move(column));
return *this;
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::Column(std::string columnName,
SqlColumnTypeDefinition columnType)
{
return Column(SqlColumnDeclaration {
.name = std::move(columnName),
.type = columnType,
});
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::RequiredColumn(std::string columnName,
SqlColumnTypeDefinition columnType)
{
return Column(SqlColumnDeclaration {
.name = std::move(columnName),
.type = columnType,
.required = true,
});
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::PrimaryKey(std::string columnName,
SqlColumnTypeDefinition columnType)
{
return Column(SqlColumnDeclaration {
.name = std::move(columnName),
.type = columnType,
.primaryKey = SqlPrimaryKeyType::MANUAL,
.required = true,
.unique = true,
.index = true,
});
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::PrimaryKeyWithAutoIncrement(std::string columnName,
SqlColumnTypeDefinition columnType)
{
return Column(SqlColumnDeclaration {
.name = std::move(columnName),
.type = columnType,
.primaryKey = SqlPrimaryKeyType::AUTO_INCREMENT,
.required = true,
.unique = true,
.index = true,
});
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::Unique()
{
_plan.columns.back().unique = true;
return *this;
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::Index()
{
_plan.columns.back().index = true;
return *this;
}

SqlCreateTableQueryBuilder& SqlCreateTableQueryBuilder::UniqueIndex()
{
_plan.columns.back().index = true;
_plan.columns.back().unique = true;
return *this;
}
117 changes: 117 additions & 0 deletions src/Lightweight/SqlQuery/Migrate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "Core.hpp"
#include "MigrationPlan.hpp"

#include <reflection-cpp/reflection.hpp>

class [[nodiscard]] SqlCreateTableQueryBuilder final
{
public:
explicit SqlCreateTableQueryBuilder(SqlCreateTablePlan& plan):
_plan { plan }
{
}

// Adds a new column to the table.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& Column(SqlColumnDeclaration column);

// Creates a new nullable column.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& Column(std::string columnName, SqlColumnTypeDefinition columnType);

// Creates a new column that is non-nullable.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& RequiredColumn(std::string columnName,
SqlColumnTypeDefinition columnType);

// Creates a new primary key column.
// Primary keys are always required, unique, have an index, and are non-nullable.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& PrimaryKey(std::string columnName, SqlColumnTypeDefinition columnType);

LIGHTWEIGHT_API SqlCreateTableQueryBuilder& PrimaryKeyWithAutoIncrement(
std::string columnName, SqlColumnTypeDefinition columnType = SqlColumnTypeDefinitions::Bigint {});

// Enables the UNIQUE constraint on the last declared column.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& Unique();

// Enables the UNIQUE constraint on the last declared column.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& Index();

// Enables the UNIQUE constraint on the last declared column and makes it an index.
LIGHTWEIGHT_API SqlCreateTableQueryBuilder& UniqueIndex();

private:
SqlCreateTablePlan& _plan;
};

class [[nodiscard]] SqlAlterTableQueryBuilder final
{
public:
explicit SqlAlterTableQueryBuilder(SqlAlterTablePlan& plan):
_plan { plan }
{
}

// Renames the table.
LIGHTWEIGHT_API SqlAlterTableQueryBuilder& RenameTo(std::string_view newTableName);

// Adds a new column to the table that is non-nullable.
LIGHTWEIGHT_API SqlAlterTableQueryBuilder& AddColumn(std::string_view columnName,
SqlColumnTypeDefinition columnType);

// Adds a new column to the table that is nullable.
LIGHTWEIGHT_API SqlAlterTableQueryBuilder& AddColumnAsNullable(std::string_view columnName,
SqlColumnTypeDefinition columnType);

// Alters the column to have a new non-nullable type.
LIGHTWEIGHT_API SqlAlterTableQueryBuilder& AlterColumn(std::string_view columnName,
SqlColumnTypeDefinition columnType);

// Alters the column to have a new nullable type.
LIGHTWEIGHT_API SqlAlterTableQueryBuilder& AlterColumnAsNullable(std::string_view columnName,
SqlColumnTypeDefinition columnType);

LIGHTWEIGHT_API SqlAlterTableQueryBuilder& RenameColumn(std::string_view oldColumnName,
std::string_view newColumnName);

LIGHTWEIGHT_API SqlAlterTableQueryBuilder& DropColumn(std::string_view columnName);

LIGHTWEIGHT_API SqlAlterTableQueryBuilder& AddIndex(std::string_view columnName);

LIGHTWEIGHT_API SqlAlterTableQueryBuilder& AddUniqueIndex(std::string_view columnName);

LIGHTWEIGHT_API SqlAlterTableQueryBuilder& DropIndex(std::string_view columnName);

private:
SqlAlterTablePlan& _plan;
};

class [[nodiscard]] SqlMigrationQueryBuilder final
{
public:
explicit SqlMigrationQueryBuilder(SqlQueryFormatter const& formatter):
_formatter { formatter },
_migrationPlan { .formatter = formatter }
{
}

LIGHTWEIGHT_API SqlMigrationQueryBuilder& CreateDatabase(std::string_view databaseName);
LIGHTWEIGHT_API SqlMigrationQueryBuilder& DropDatabase(std::string_view databaseName);

LIGHTWEIGHT_API SqlCreateTableQueryBuilder CreateTable(std::string_view tableName);
LIGHTWEIGHT_API SqlAlterTableQueryBuilder AlterTable(std::string_view tableName);
LIGHTWEIGHT_API SqlMigrationQueryBuilder& DropTable(std::string_view tableName);

LIGHTWEIGHT_API SqlMigrationQueryBuilder& RawSql(std::string_view sql);
LIGHTWEIGHT_API SqlMigrationQueryBuilder& Native(std::function<std::string(SqlConnection&)> callback);

LIGHTWEIGHT_API SqlMigrationQueryBuilder& BeginTransaction();
LIGHTWEIGHT_API SqlMigrationQueryBuilder& CommitTransaction();

LIGHTWEIGHT_API SqlMigrationPlan GetPlan();

private:
SqlQueryFormatter const& _formatter;
SqlMigrationPlan _migrationPlan;
};
Loading

0 comments on commit 0af1dc4

Please sign in to comment.