4#include "../SqlQueryFormatter.hpp"
6#include <reflection-cpp/reflection.hpp>
13class SQLiteQueryFormatter:
public SqlQueryFormatter
16 [[nodiscard]] std::string Insert(std::string_view intoTable,
17 std::string_view fields,
18 std::string_view values)
const override
20 return std::format(R
"(INSERT INTO "{}" ({}) VALUES ({}))", intoTable, fields, values);
23 [[nodiscard]] std::string QueryLastInsertId(std::string_view )
const override
26 return "SELECT LAST_INSERT_ROWID()";
29 [[nodiscard]] std::string_view BooleanLiteral(
bool literalValue)
const noexcept override
31 return literalValue ?
"TRUE" :
"FALSE";
34 [[nodiscard]] std::string StringLiteral(std::string_view value)
const noexcept override
37 return std::format(
"'{}'", value);
40 [[nodiscard]] std::string StringLiteral(
char value)
const noexcept override
43 return std::format(
"'{}'", value);
46 [[nodiscard]] std::string SelectCount(
bool distinct,
47 std::string_view fromTable,
48 std::string_view fromTableAlias,
49 std::string_view tableJoins,
50 std::string_view whereCondition)
const override
52 if (fromTableAlias.empty())
54 R
"(SELECT{} COUNT(*) FROM "{}"{}{})", distinct ? " DISTINCT" :
"", fromTable, tableJoins, whereCondition);
56 return std::format(R
"(SELECT{} COUNT(*) FROM "{}" AS "{}"{}{})",
57 distinct ? " DISTINCT" :
"",
64 [[nodiscard]] std::string SelectAll(
bool distinct,
66 std::string_view fields,
67 std::string_view fromTable,
68 std::string_view fromTableAlias,
69 std::string_view tableJoins,
70 std::string_view whereCondition,
71 std::string_view orderBy,
72 std::string_view groupBy)
const override
74 std::stringstream sqlQueryString;
75 sqlQueryString <<
"SELECT ";
77 sqlQueryString <<
"DISTINCT ";
78 sqlQueryString << fields;
79 sqlQueryString <<
" FROM \"" << fromTable <<
'"';
80 if (!fromTableAlias.empty())
81 sqlQueryString <<
" AS \"" << fromTableAlias <<
'"';
82 sqlQueryString << tableJoins;
83 sqlQueryString << whereCondition;
84 sqlQueryString << groupBy;
85 sqlQueryString << orderBy;
87 return sqlQueryString.str();
90 [[nodiscard]] std::string SelectFirst(
bool distinct,
92 std::string_view fields,
93 std::string_view fromTable,
94 std::string_view fromTableAlias,
95 std::string_view tableJoins,
96 std::string_view whereCondition,
97 std::string_view orderBy,
98 size_t count)
const override
100 std::stringstream sqlQueryString;
101 sqlQueryString <<
"SELECT " << fields;
103 sqlQueryString <<
" DISTINCT";
104 sqlQueryString <<
" FROM \"" << fromTable <<
"\"";
105 if (!fromTableAlias.empty())
106 sqlQueryString <<
" AS \"" << fromTableAlias <<
"\"";
107 sqlQueryString << tableJoins;
108 sqlQueryString << whereCondition;
109 sqlQueryString << orderBy;
110 sqlQueryString <<
" LIMIT " << count;
111 return sqlQueryString.str();
114 [[nodiscard]] std::string SelectRange(
bool distinct,
116 std::string_view fields,
117 std::string_view fromTable,
118 std::string_view fromTableAlias,
119 std::string_view tableJoins,
120 std::string_view whereCondition,
121 std::string_view orderBy,
122 std::string_view groupBy,
124 std::size_t limit)
const override
126 std::stringstream sqlQueryString;
127 sqlQueryString <<
"SELECT " << fields;
129 sqlQueryString <<
" DISTINCT";
130 sqlQueryString <<
" FROM \"" << fromTable <<
"\"";
131 if (!fromTableAlias.empty())
132 sqlQueryString <<
" AS \"" << fromTableAlias <<
"\"";
133 sqlQueryString << tableJoins;
134 sqlQueryString << whereCondition;
135 sqlQueryString << groupBy;
136 sqlQueryString << orderBy;
137 sqlQueryString <<
" LIMIT " << limit <<
" OFFSET " << offset;
138 return sqlQueryString.str();
141 [[nodiscard]] std::string Update(std::string_view table,
142 std::string_view tableAlias,
143 std::string_view setFields,
144 std::string_view whereCondition)
const override
146 if (tableAlias.empty())
147 return std::format(R
"(UPDATE "{}" SET {}{})", table, setFields, whereCondition);
149 return std::format(R
"(UPDATE "{}" AS "{}" SET {}{})", table, tableAlias, setFields, whereCondition);
152 [[nodiscard]] std::string Delete(std::string_view fromTable,
153 std::string_view fromTableAlias,
154 std::string_view tableJoins,
155 std::string_view whereCondition) const override
157 if (fromTableAlias.empty())
158 return std::format(R
"(DELETE FROM "{}"{}{})", fromTable, tableJoins, whereCondition);
160 return std::format(R
"(DELETE FROM "{}" AS "{}"{}{})", fromTable, fromTableAlias, tableJoins, whereCondition);
163 [[nodiscard]] virtual std::string BuildColumnDefinition(SqlColumnDeclaration
const& column)
const
165 std::stringstream sqlQueryString;
167 sqlQueryString <<
'"' << column.name <<
"\" ";
169 if (column.primaryKey != SqlPrimaryKeyType::AUTO_INCREMENT)
170 sqlQueryString << ColumnType(column.type);
172 sqlQueryString << ColumnType(SqlColumnTypeDefinitions::Integer {});
175 sqlQueryString <<
" NOT NULL";
177 if (column.primaryKey == SqlPrimaryKeyType::AUTO_INCREMENT)
178 sqlQueryString <<
" PRIMARY KEY AUTOINCREMENT";
179 else if (column.primaryKey == SqlPrimaryKeyType::NONE && !column.index && column.unique)
180 sqlQueryString <<
" UNIQUE";
182 return sqlQueryString.str();
185 [[nodiscard]]
static std::string BuildForeignKeyConstraint(std::string_view columnName,
186 SqlForeignKeyReferenceDefinition
const& referencedColumn)
188 return std::format(R
"(CONSTRAINT {} FOREIGN KEY ("{}") REFERENCES "{}"("{}"))",
189 std::format("FK_{}", columnName),
191 referencedColumn.tableName,
192 referencedColumn.columnName);
196 [[nodiscard]] StringList CreateTable(std::string_view tableName,
197 std::vector<SqlColumnDeclaration>
const& columns)
const override
199 auto sqlQueries = StringList {};
201 sqlQueries.emplace_back([&]() {
202 std::stringstream sqlQueryString;
203 sqlQueryString <<
"CREATE TABLE \"" << tableName <<
"\" (";
204 size_t currentColumn = 0;
205 std::string primaryKeyColumns;
206 std::string foreignKeyConstraints;
207 for (SqlColumnDeclaration
const& column: columns)
209 if (currentColumn > 0)
210 sqlQueryString <<
",";
212 sqlQueryString <<
"\n ";
213 sqlQueryString << BuildColumnDefinition(column);
214 if (column.primaryKey == SqlPrimaryKeyType::MANUAL || column.primaryKey == SqlPrimaryKeyType::GUID)
216 if (!primaryKeyColumns.empty())
217 primaryKeyColumns +=
", ";
218 primaryKeyColumns +=
'"';
219 primaryKeyColumns += column.name;
220 primaryKeyColumns +=
'"';
222 if (column.foreignKey)
224 foreignKeyConstraints +=
",\n ";
225 foreignKeyConstraints += BuildForeignKeyConstraint(column.name, *column.foreignKey);
228 if (!primaryKeyColumns.empty())
229 sqlQueryString <<
",\n PRIMARY KEY (" << primaryKeyColumns <<
")";
231 sqlQueryString << foreignKeyConstraints;
233 sqlQueryString <<
"\n);";
234 return sqlQueryString.str();
237 for (SqlColumnDeclaration
const& column: columns)
239 if (column.index && column.primaryKey == SqlPrimaryKeyType::NONE)
243 sqlQueries.emplace_back(std::format(R
"(CREATE UNIQUE INDEX "{}_{}_index" ON "{}"("{}");)",
249 sqlQueries.emplace_back(std::format(
250 R
"(CREATE INDEX "{}_{}_index" ON "{}"("{}");)", tableName, column.name, tableName, column.name));
257 [[nodiscard]] StringList AlterTable(std::string_view tableName,
258 std::vector<SqlAlterTableCommand>
const& commands)
const override
260 std::stringstream sqlQueryString;
262 int currentCommand = 0;
263 for (SqlAlterTableCommand
const& command: commands)
265 if (currentCommand > 0)
266 sqlQueryString <<
'\n';
269 using namespace SqlAlterTableCommands;
270 sqlQueryString << std::visit(
272 [tableName](RenameTable
const& actualCommand) -> std::string {
273 return std::format(R
"(ALTER TABLE "{}" RENAME TO "{}";)", tableName, actualCommand.newTableName);
275 [tableName, this](AddColumn
const& actualCommand) -> std::string {
276 return std::format(R
"(ALTER TABLE "{}" ADD COLUMN "{}" {} {};)",
278 actualCommand.columnName,
279 ColumnType(actualCommand.columnType),
280 actualCommand.nullable == SqlNullable::NotNull ? "NOT NULL" :
"NULL");
282 [tableName,
this](AlterColumn
const& actualCommand) -> std::string {
283 return std::format(R
"(ALTER TABLE "{}" ALTER COLUMN "{}" {} {};)",
285 actualCommand.columnName,
286 ColumnType(actualCommand.columnType),
287 actualCommand.nullable == SqlNullable::NotNull ? "NOT NULL" :
"NULL");
289 [tableName](RenameColumn
const& actualCommand) -> std::string {
290 return std::format(R
"(ALTER TABLE "{}" RENAME COLUMN "{}" TO "{}";)",
292 actualCommand.oldColumnName,
293 actualCommand.newColumnName);
295 [tableName](DropColumn const& actualCommand) -> std::string {
296 return std::format(R
"(ALTER TABLE "{}" DROP COLUMN "{}";)", tableName, actualCommand.columnName);
298 [tableName](AddIndex const& actualCommand) -> std::string {
299 using namespace std::string_view_literals;
300 auto const uniqueStr = actualCommand.unique ?
"UNIQUE "sv :
""sv;
301 return std::format(R
"(CREATE {2}INDEX "{0}_{1}_index" ON "{0}"("{1}");)",
303 actualCommand.columnName,
306 [tableName](DropIndex const& actualCommand) -> std::string {
307 return std::format(R
"(DROP INDEX "{0}_{1}_index";)", tableName, actualCommand.columnName);
309 [tableName](AddForeignKey const& actualCommand) -> std::string {
311 R
"(ALTER TABLE "{}" ADD {};)",
313 BuildForeignKeyConstraint(actualCommand.columnName, actualCommand.referencedColumn));
315 [tableName](DropForeignKey const& actualCommand) -> std::string {
316 return std::format(R
"(ALTER TABLE "{}" DROP CONSTRAINT "{}";)",
318 std::format("FK_{}", actualCommand.columnName));
324 return { sqlQueryString.str() };
327 [[nodiscard]] std::string ColumnType(SqlColumnTypeDefinition
const& type)
const override
329 using namespace SqlColumnTypeDefinitions;
330 return std::visit(detail::overloaded {
331 [](Bigint
const&) -> std::string {
return "BIGINT"; },
332 [](Binary
const&) -> std::string {
return "BLOB"; },
333 [](Bool
const&) -> std::string {
return "BOOLEAN"; },
334 [](Char
const& type) -> std::string {
return std::format(
"CHAR({})", type.size); },
335 [](Date
const&) -> std::string {
return "DATE"; },
336 [](DateTime
const&) -> std::string {
return "DATETIME"; },
337 [](Decimal
const& type) -> std::string {
338 return std::format(
"DECIMAL({}, {})", type.precision, type.scale);
340 [](Guid
const&) -> std::string {
return "GUID"; },
341 [](Integer
const&) -> std::string {
return "INTEGER"; },
342 [](NChar
const& type) -> std::string {
return std::format(
"NCHAR({})", type.size); },
343 [](NVarchar
const& type) -> std::string {
return std::format(
"NVARCHAR({})", type.size); },
344 [](Real
const&) -> std::string {
return "REAL"; },
345 [](Smallint
const&) -> std::string {
return "SMALLINT"; },
346 [](Text
const&) -> std::string {
return "TEXT"; },
347 [](Time
const&) -> std::string {
return "TIME"; },
348 [](Timestamp
const&) -> std::string {
return "TIMESTAMP"; },
349 [](Tinyint
const&) -> std::string {
return "TINYINT"; },
350 [](VarBinary
const& type) -> std::string {
return std::format(
"VARBINARY({})", type.size); },
351 [](Varchar
const& type) -> std::string {
return std::format(
"VARCHAR({})", type.size); },
356 [[nodiscard]] StringList DropTable(std::string_view
const& tableName)
const override
358 return { std::format(R
"(DROP TABLE "{}";)", tableName) };