4#include "../SqlQueryFormatter.hpp"
5#include "SQLiteFormatter.hpp"
7#include <reflection-cpp/reflection.hpp>
14class PostgreSqlFormatter final:
public SQLiteQueryFormatter
17 using SQLiteQueryFormatter::CreateTable;
19 [[nodiscard]] StringList DropTable(std::string_view schemaName,
20 std::string_view
const& tableName,
21 bool ifExists =
false,
22 bool cascade =
false)
const override
24 std::string sql = ifExists ? std::format(
"DROP TABLE IF EXISTS {}", FormatTableName(schemaName, tableName))
25 : std::format(
"DROP TABLE {}", FormatTableName(schemaName, tableName));
32 [[nodiscard]] std::string BinaryLiteral(std::span<uint8_t const> data)
const override
35 result.reserve((data.size() * 2) + 4);
37 for (uint8_t
byte: data)
38 result += std::format(
"{:02X}", byte);
43 [[nodiscard]] std::string QueryLastInsertId(std::string_view )
const override
48 return std::format(
"SELECT lastval();");
51 [[nodiscard]] std::string_view DateFunction() const noexcept
override
53 return "CURRENT_DATE";
56 [[nodiscard]] std::string BuildColumnDefinition(SqlColumnDeclaration
const& column)
const override
58 std::stringstream sqlQueryString;
60 sqlQueryString <<
'"' << column.name <<
"\" ";
65 bool const isAutoIncrementViaDefault = column.defaultValue.find(
"nextval(") != std::string::npos;
66 bool const isAutoIncrement = column.primaryKey == SqlPrimaryKeyType::AUTO_INCREMENT || isAutoIncrementViaDefault;
69 sqlQueryString <<
"SERIAL";
71 sqlQueryString << ColumnType(column.type);
74 sqlQueryString <<
" NOT NULL";
79 if (column.primaryKey == SqlPrimaryKeyType::AUTO_INCREMENT)
80 sqlQueryString <<
" PRIMARY KEY";
81 else if (column.primaryKey == SqlPrimaryKeyType::NONE && !column.index && column.unique)
82 sqlQueryString <<
" UNIQUE";
85 if (!column.defaultValue.empty() && !isAutoIncrement)
86 sqlQueryString <<
" DEFAULT " << column.defaultValue;
88 return sqlQueryString.str();
91 [[nodiscard]] std::string ColumnType(SqlColumnTypeDefinition
const& type)
const override
93 using namespace SqlColumnTypeDefinitions;
96 return std::visit(detail::overloaded {
97 [](Bigint
const&) -> std::string {
return "BIGINT"; },
98 [](Binary
const& type) -> std::string {
return std::format(
"BYTEA", type.size); },
99 [](Bool
const&) -> std::string {
return "BOOLEAN"; },
100 [](Char
const& type) -> std::string {
return std::format(
"CHAR({})", type.size); },
101 [](Date
const&) -> std::string {
return "DATE"; },
102 [](DateTime
const&) -> std::string {
return "TIMESTAMP"; },
103 [](Decimal
const& type) -> std::string {
104 return std::format(
"DECIMAL({}, {})", type.precision, type.scale);
106 [](Guid
const&) -> std::string {
return "UUID"; },
107 [](Integer
const&) -> std::string {
return "INTEGER"; },
108 [](NChar
const& type) -> std::string {
return std::format(
"CHAR({})", type.size); },
109 [](NVarchar
const& type) -> std::string {
112 return std::format(
"VARCHAR({})", type.size);
114 [](Real
const&) -> std::string {
return "REAL"; },
115 [](Smallint
const&) -> std::string {
return "SMALLINT"; },
116 [](Text
const&) -> std::string {
return "TEXT"; },
117 [](Time
const&) -> std::string {
return "TIME"; },
118 [](Timestamp
const&) -> std::string {
return "TIMESTAMP"; },
120 [](Tinyint
const&) -> std::string {
return "SMALLINT"; },
121 [](VarBinary
const& ) -> std::string {
return std::format(
"BYTEA"); },
122 [](Varchar
const& type) -> std::string {
125 return std::format(
"VARCHAR({})", type.size);
132 [[nodiscard]] StringList AlterTable(std::string_view schemaName,
133 std::string_view tableName,
134 std::vector<SqlAlterTableCommand>
const& commands)
const override
136 std::stringstream sqlQueryString;
138 int currentCommand = 0;
139 for (SqlAlterTableCommand
const& command: commands)
141 if (currentCommand > 0)
142 sqlQueryString <<
'\n';
145 using namespace SqlAlterTableCommands;
146 sqlQueryString << std::visit(
148 [schemaName, tableName](RenameTable
const& actualCommand) -> std::string {
149 return std::format(R
"(ALTER TABLE {} RENAME TO "{}";)",
150 FormatTableName(schemaName, tableName),
151 actualCommand.newTableName);
153 [schemaName, tableName, this](AddColumn
const& actualCommand) -> std::string {
154 return std::format(R
"(ALTER TABLE {} ADD COLUMN "{}" {} {};)",
155 FormatTableName(schemaName, tableName),
156 actualCommand.columnName,
157 ColumnType(actualCommand.columnType),
158 actualCommand.nullable == SqlNullable::NotNull ? "NOT NULL" :
"NULL");
160 [schemaName, tableName,
this](AlterColumn
const& actualCommand) -> std::string {
162 R
"(ALTER TABLE {0} ALTER COLUMN "{1}" TYPE {2}, ALTER COLUMN "{1}" {3} NOT NULL;)",
163 FormatTableName(schemaName, tableName),
164 actualCommand.columnName,
165 ColumnType(actualCommand.columnType),
166 actualCommand.nullable == SqlNullable::NotNull ? "SET" :
"DROP");
168 [schemaName, tableName](RenameColumn
const& actualCommand) -> std::string {
169 return std::format(R
"(ALTER TABLE {} RENAME COLUMN "{}" TO "{}";)",
170 FormatTableName(schemaName, tableName),
171 actualCommand.oldColumnName,
172 actualCommand.newColumnName);
174 [schemaName, tableName](DropColumn const& actualCommand) -> std::string {
175 return std::format(R
"(ALTER TABLE {} DROP COLUMN "{}";)",
176 FormatTableName(schemaName, tableName),
177 actualCommand.columnName);
179 [schemaName, tableName](AddIndex const& actualCommand) -> std::string {
180 using namespace std::string_view_literals;
181 auto const uniqueStr = actualCommand.unique ?
"UNIQUE "sv :
""sv;
182 if (schemaName.empty())
183 return std::format(R
"(CREATE {2}INDEX "{0}_{1}_index" ON "{0}" ("{1}");)",
185 actualCommand.columnName,
188 return std::format(R
"(CREATE {3}INDEX "{0}_{1}_{2}_index" ON "{0}"."{1}" ("{2}");)",
191 actualCommand.columnName,
194 [schemaName, tableName](DropIndex const& actualCommand) -> std::string {
195 if (schemaName.empty())
196 return std::format(R
"(DROP INDEX "{0}_{1}_index";)", tableName, actualCommand.columnName);
199 R
"(DROP INDEX "{0}_{1}_{2}_index";)", schemaName, tableName, actualCommand.columnName);
201 [schemaName, tableName](AddForeignKey const& actualCommand) -> std::string {
203 R
"(ALTER TABLE {} ADD {};)",
204 FormatTableName(schemaName, tableName),
205 BuildForeignKeyConstraint(tableName, actualCommand.columnName, actualCommand.referencedColumn));
207 [schemaName, tableName](DropForeignKey const& actualCommand) -> std::string {
208 return std::format(R
"(ALTER TABLE {} DROP CONSTRAINT "{}";)",
209 FormatTableName(schemaName, tableName),
210 std::format("FK_{}_{}", tableName, actualCommand.columnName));
212 [schemaName, tableName](AddCompositeForeignKey
const& actualCommand) -> std::string {
213 std::stringstream ss;
214 ss <<
"ALTER TABLE " << FormatTableName(schemaName, tableName) <<
" ADD CONSTRAINT "
215 << std::format(
"\"FK_{}_{}\"", tableName, actualCommand.columns[0]) <<
" FOREIGN KEY (";
218 for (
auto const& col: actualCommand.columns)
222 ss <<
'"' << col <<
'"';
224 ss <<
") REFERENCES " << FormatTableName(schemaName, actualCommand.referencedTableName) <<
" (";
227 for (
auto const& col: actualCommand.referencedColumns)
231 ss <<
'"' << col <<
'"';
236 [schemaName, tableName,
this](AddColumnIfNotExists
const& actualCommand) -> std::string {
238 return std::format(R
"(ALTER TABLE {} ADD COLUMN IF NOT EXISTS "{}" {} {};)",
239 FormatTableName(schemaName, tableName),
240 actualCommand.columnName,
241 ColumnType(actualCommand.columnType),
242 actualCommand.nullable == SqlNullable::NotNull ? "NOT NULL" :
"NULL");
244 [schemaName, tableName](DropColumnIfExists
const& actualCommand) -> std::string {
246 return std::format(R
"(ALTER TABLE {} DROP COLUMN IF EXISTS "{}";)",
247 FormatTableName(schemaName, tableName),
248 actualCommand.columnName);
250 [schemaName, tableName](DropIndexIfExists const& actualCommand) -> std::string {
252 if (schemaName.empty())
254 R
"(DROP INDEX IF EXISTS "{0}_{1}_index";)", tableName, actualCommand.columnName);
256 return std::format(R
"(DROP INDEX IF EXISTS "{0}_{1}_{2}_index";)",
259 actualCommand.columnName);
265 return { sqlQueryString.str() };
268 [[nodiscard]] std::string QueryServerVersion()
const override
270 return "SELECT version()";