4#include "../SqlQueryFormatter.hpp"
5#include "SQLiteFormatter.hpp"
7#include <reflection-cpp/reflection.hpp>
15class SqlServerQueryFormatter final:
public SQLiteQueryFormatter
18 [[nodiscard]] std::string QueryLastInsertId(std::string_view )
const override
21 return std::format(
"SELECT @@IDENTITY");
24 [[nodiscard]] std::string_view BooleanLiteral(
bool literalValue)
const noexcept override
26 return literalValue ?
"1" :
"0";
29 [[nodiscard]] std::string SelectFirst(
bool distinct,
31 std::string_view fields,
32 std::string_view fromTable,
33 std::string_view fromTableAlias,
34 std::string_view tableJoins,
35 std::string_view whereCondition,
36 std::string_view orderBy,
37 size_t count)
const override
39 std::stringstream sqlQueryString;
40 sqlQueryString <<
"SELECT";
42 sqlQueryString <<
" DISTINCT";
43 sqlQueryString <<
" TOP " << count;
44 sqlQueryString <<
' ' << fields;
45 sqlQueryString <<
" FROM \"" << fromTable <<
'"';
46 if (!fromTableAlias.empty())
47 sqlQueryString <<
" AS \"" << fromTableAlias <<
'"';
48 sqlQueryString << tableJoins;
49 sqlQueryString << whereCondition;
50 sqlQueryString << orderBy;
52 return sqlQueryString.str();
55 [[nodiscard]] std::string SelectRange(
bool distinct,
57 std::string_view fields,
58 std::string_view fromTable,
59 std::string_view fromTableAlias,
60 std::string_view tableJoins,
61 std::string_view whereCondition,
62 std::string_view orderBy,
63 std::string_view groupBy,
65 std::size_t limit)
const override
67 assert(!orderBy.empty());
68 std::stringstream sqlQueryString;
69 sqlQueryString <<
"SELECT " << fields;
71 sqlQueryString <<
" DISTINCT";
72 sqlQueryString <<
" FROM \"" << fromTable <<
"\"";
73 if (!fromTableAlias.empty())
74 sqlQueryString <<
" AS \"" << fromTableAlias <<
"\"";
75 sqlQueryString << tableJoins;
76 sqlQueryString << whereCondition;
77 sqlQueryString << groupBy;
78 sqlQueryString << orderBy;
79 sqlQueryString <<
" OFFSET " << offset <<
" ROWS FETCH NEXT " << limit <<
" ROWS ONLY";
80 return sqlQueryString.str();
83 [[nodiscard]] std::string ColumnType(SqlColumnTypeDefinition
const& type)
const override
85 using namespace SqlColumnTypeDefinitions;
86 return std::visit(detail::overloaded {
87 [](Bigint
const&) -> std::string {
return "BIGINT"; },
88 [](Binary
const& type) -> std::string {
return std::format(
"VARBINARY({})", type.size); },
89 [](Bool
const&) -> std::string {
return "BIT"; },
90 [](Char
const& type) -> std::string {
return std::format(
"CHAR({})", type.size); },
91 [](Date
const&) -> std::string {
return "DATE"; },
92 [](DateTime
const&) -> std::string {
return "DATETIME"; },
93 [](Decimal
const& type) -> std::string {
94 return std::format(
"DECIMAL({}, {})", type.precision, type.scale);
96 [](Guid
const&) -> std::string {
return "UNIQUEIDENTIFIER"; },
97 [](Integer
const&) -> std::string {
return "INTEGER"; },
98 [](NChar
const& type) -> std::string {
return std::format(
"NCHAR({})", type.size); },
99 [](NVarchar
const& type) -> std::string {
100 if (type.size == 0 || type.size > SqlOptimalMaxColumnSize)
101 return "NVARCHAR(MAX)";
103 return std::format(
"NVARCHAR({})", type.size);
105 [](Real
const&) -> std::string {
return "REAL"; },
106 [](Smallint
const&) -> std::string {
return "SMALLINT"; },
107 [](Text
const&) -> std::string {
return "VARCHAR(MAX)"; },
108 [](Time
const&) -> std::string {
return "TIME"; },
109 [](Timestamp
const&) -> std::string {
return "TIMESTAMP"; },
110 [](Tinyint
const&) -> std::string {
return "TINYINT"; },
111 [](VarBinary
const& type) -> std::string {
return std::format(
"VARBINARY({})", type.size); },
112 [](Varchar
const& type) -> std::string {
113 if (type.size == 0 || type.size > SqlOptimalMaxColumnSize)
114 return "VARCHAR(MAX)";
116 return std::format(
"VARCHAR({})", type.size);
122 [[nodiscard]] std::string BuildColumnDefinition(SqlColumnDeclaration
const& column)
const override
124 std::stringstream sqlQueryString;
125 sqlQueryString <<
'"' << column.name <<
"\" " << ColumnType(column.type);
128 sqlQueryString <<
" NOT NULL";
130 if (column.primaryKey == SqlPrimaryKeyType::AUTO_INCREMENT)
131 sqlQueryString <<
" IDENTITY(1,1) PRIMARY KEY";
132 else if (column.primaryKey == SqlPrimaryKeyType::NONE && !column.index && column.unique)
133 sqlQueryString <<
" UNIQUE";
135 return sqlQueryString.str();
138 [[nodiscard]] StringList AlterTable(std::string_view tableName,
139 std::vector<SqlAlterTableCommand>
const& commands)
const override
141 std::stringstream sqlQueryString;
143 int currentCommand = 0;
144 for (SqlAlterTableCommand
const& command: commands)
146 if (currentCommand > 0)
147 sqlQueryString <<
'\n';
150 using namespace SqlAlterTableCommands;
151 sqlQueryString << std::visit(
153 [tableName](RenameTable
const& actualCommand) -> std::string {
154 return std::format(R
"(ALTER TABLE "{}" RENAME TO "{}";)", tableName, actualCommand.newTableName);
156 [tableName, this](AddColumn
const& actualCommand) -> std::string {
157 return std::format(R
"(ALTER TABLE "{}" ADD "{}" {} {};)",
159 actualCommand.columnName,
160 ColumnType(actualCommand.columnType),
161 actualCommand.nullable == SqlNullable::NotNull ? "NOT NULL" :
"NULL");
163 [tableName,
this](AlterColumn
const& actualCommand) -> std::string {
164 return std::format(R
"(ALTER TABLE "{}" ALTER COLUMN "{}" {} {};)",
166 actualCommand.columnName,
167 ColumnType(actualCommand.columnType),
168 actualCommand.nullable == SqlNullable::NotNull ? "NOT NULL" :
"NULL");
170 [tableName](RenameColumn
const& actualCommand) -> std::string {
171 return std::format(R
"(ALTER TABLE "{}" RENAME COLUMN "{}" TO "{}";)",
173 actualCommand.oldColumnName,
174 actualCommand.newColumnName);
176 [tableName](DropColumn const& actualCommand) -> std::string {
177 return std::format(R
"(ALTER TABLE "{}" DROP COLUMN "{}";)", tableName, actualCommand.columnName);
179 [tableName](AddIndex const& actualCommand) -> std::string {
180 using namespace std::string_view_literals;
181 auto const uniqueStr = actualCommand.unique ?
"UNIQUE "sv :
""sv;
182 return std::format(R
"(CREATE {2}INDEX "{0}_{1}_index" ON "{0}"("{1}");)",
184 actualCommand.columnName,
187 [tableName](DropIndex const& actualCommand) -> std::string {
188 return std::format(R
"(DROP INDEX "{0}_{1}_index";)", tableName, actualCommand.columnName);
190 [tableName](AddForeignKey const& actualCommand) -> std::string {
192 R
"(ALTER TABLE "{}" ADD {};)",
194 BuildForeignKeyConstraint(actualCommand.columnName, actualCommand.referencedColumn));
196 [tableName](DropForeignKey const& actualCommand) -> std::string {
197 return std::format(R
"(ALTER TABLE "{}" DROP CONSTRAINT "{}";)",
199 std::format("FK_{}", actualCommand.columnName));
205 return { sqlQueryString.str() };