Lightweight 0.20260617.0
Loading...
Searching...
No Matches
CxxModelPrinter.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include <Lightweight/DataMapper/Field.hpp>
6#include <Lightweight/SqlSchema.hpp>
7#include <Lightweight/Utils.hpp>
8
9#include <expected>
10#include <filesystem>
11#include <map>
12#include <string>
13#include <unordered_set>
14#include <utility>
15#include <vector>
16
17namespace Lightweight::Tools
18{
19
20using ColumnNameOverrides = std::map<SqlSchema::ColumnIdentifier, std::string>;
21
22class CxxModelPrinter
23{
24 public:
25 using UnicodeTextColumnOverrides = std::unordered_map<std::string /*table*/, std::unordered_set<std::string /*column*/>>;
26
27 struct Config
28 {
29 std::vector<std::string> stripSuffixes = { "_id", "_nr" };
30 bool makeAliases = false;
31 FormatType formatType = FormatType::camelCase;
32 PrimaryKey primaryKeyAssignment = PrimaryKey::ServerSideAutoIncrement;
33 ColumnNameOverrides columnNameOverrides;
34 bool forceUnicodeTextColumns = false;
35 UnicodeTextColumnOverrides unicodeTextColumnOverrides;
36 bool suppressWarnings = false;
37 size_t sqlFixedStringMaxSize = SqlOptimalMaxColumnSize;
38 /// When set, emit `extern template` declarations in the headers plus one explicit-
39 /// instantiation .cpp per record and a CMakeLists.txt that builds them into a library.
40 /// Consuming translation units then link that library instead of re-instantiating the
41 /// (expensive) DataMapper relation machinery for every record.
42 bool generateInstantiations = false;
43 /// Name of the CMake library target emitted alongside the instantiation sources.
44 std::string instantiationTargetName = "LightweightEntities";
45 };
46
47 explicit CxxModelPrinter(Config config) noexcept;
48
49 std::string ToString(std::string_view modelNamespace);
50
51 [[nodiscard]] std::string TableIncludes() const;
52
53 [[nodiscard]] std::string AliasTableName(std::string_view name) const;
54
55 [[nodiscard]] std::expected<void, std::string> PrintCumulativeHeaderFile(
56 std::filesystem::path const& outputDirectory, std::filesystem::path const& cumulativeHeaderFile);
57
58 void PrintToFiles(std::string_view modelNamespace, std::string_view outputDirectory);
59
60 std::string HeaderFileForTheTable(std::string_view modelNamespace, std::string const& tableName);
61
62 [[nodiscard]] std::string Example(SqlSchema::Table const& table) const;
63
64 auto StripSuffix(std::string name) -> std::string;
65
66 static auto SanitizeName(std::string name) -> std::string;
67
68 static auto FormatTableName(std::string_view name) -> std::string;
69
70 static SqlSchema::ForeignKeyConstraint const& GetForeignKey(
71 SqlSchema::Column const& column, std::vector<SqlSchema::ForeignKeyConstraint> const& foreignKeys);
72
73 static std::string MakeType(SqlSchema::Column const& column,
74 std::string const& tableName,
75 bool forceUnicodeTextColumn,
76 UnicodeTextColumnOverrides const& unicodeTextColumnOverrides,
77 size_t sqlFixedStringMaxSize);
78
79 [[nodiscard]] std::optional<std::string> MapColumnNameOverride(SqlSchema::FullyQualifiedTableName const& tableName,
80 std::string const& columnName) const;
81
82 void ResolveOrderAndPrintTable(std::vector<SqlSchema::Table> const& tables);
83
84 void PrintTable(SqlSchema::Table const& table);
85
86 void PrintReport();
87
88 private:
89 // Writes the CMakeLists.txt that builds the per-record instantiation sources into a library.
90 void WriteInstantiationCMakeLists(std::string_view outputDirectory, std::vector<std::string> instantiationSources) const;
91
92 struct TableInfo
93 {
94 std::stringstream text;
95 std::vector<std::string> requiredTables;
96 std::string structName; //< C++ struct name (possibly aliased).
97 std::vector<std::pair<std::string, std::string>> members; //< (emitted member id, SQL column name), in order.
98 };
99
100 // Renders the Description<> specialization for one table (emitted at global scope so it
101 // can specialize the Lightweight customization point). Returns empty if there is nothing to emit.
102 [[nodiscard]] static std::string RecordDescriptorFor(std::string_view modelNamespace, TableInfo const& info);
103
104 // Renders the `extern template` declaration appended to a record's header so consuming TUs do
105 // not implicitly instantiate the heavy relation machinery. Returns empty if nothing to emit.
106 [[nodiscard]] static std::string ExternTemplateDeclarationFor(std::string_view modelNamespace, TableInfo const& info);
107
108 // Renders the .cpp that explicitly instantiates a record's relation machinery exactly once.
109 [[nodiscard]] static std::string InstantiationSourceFor(std::string_view modelNamespace,
110 std::string const& headerFileName,
111 TableInfo const& info);
112
113 std::map<std::string, TableInfo> _definitions;
114 Config _config;
115 std::map<SqlSchema::FullyQualifiedTableName, SqlSchema::ForeignKeyConstraint> _warningOnUnsupportedMultiKeyForeignKey;
116 size_t _numberOfColumnsListed = 0;
117 size_t _numberOfForeignKeysListed = 0;
118};
119
120} // namespace Lightweight::Tools