Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
database::detail::sql_dialect Class Referencefinal

SQL dialect implementation for PostgreSQL, SQLite. More...

#include <query_dialect.h>

Inheritance diagram for database::detail::sql_dialect:
Inheritance graph
Collaboration diagram for database::detail::sql_dialect:
Collaboration graph

Public Member Functions

 sql_dialect (database_types db_type)
 
 ~sql_dialect () override=default
 
void set_query_type (query_type type) override
 
query_type get_query_type () const override
 
void set_select_columns (const std::vector< std::string > &columns) override
 
void set_from_table (const std::string &table) override
 
void add_where_condition (const query_condition &condition) override
 
void add_where_condition (const std::string &field, const std::string &op, const core::database_value &value) override
 
void add_join (const std::string &table, const std::string &condition, join_type type) override
 
void set_group_by (const std::vector< std::string > &columns) override
 
void set_having (const std::string &condition) override
 
void add_order_by (const std::string &column, sort_order order) override
 
void set_limit (size_t count) override
 
void set_offset (size_t count) override
 
void set_insert_table (const std::string &table) override
 
void set_insert_data (const std::map< std::string, core::database_value > &data) override
 
void set_insert_rows (const std::vector< std::map< std::string, core::database_value > > &rows) override
 
void set_update_table (const std::string &table) override
 
void set_update_data (const std::map< std::string, core::database_value > &data) override
 
void set_delete_table (const std::string &table) override
 
void set_collection (const std::string &name) override
 
void set_key (const std::string &key) override
 
std::string build () const override
 
void reset () override
 
database_types get_database_type () const override
 
- Public Member Functions inherited from database::query_dialect
virtual ~query_dialect ()=default
 

Private Member Functions

std::string escape_identifier (const std::string &identifier) const
 
std::string format_value (const core::database_value &value) const
 
std::string join_type_to_string (join_type type) const
 

Private Attributes

database_types db_type_
 
query_type type_
 
std::vector< std::string > select_columns_
 
std::string from_table_
 
std::vector< query_conditionwhere_conditions_
 
std::vector< std::string > joins_
 
std::vector< std::string > group_by_columns_
 
std::string having_clause_
 
std::vector< std::string > order_by_clauses_
 
size_t limit_count_
 
size_t offset_count_
 
std::string target_table_
 
std::map< std::string, core::database_valueset_data_
 
std::vector< std::map< std::string, core::database_value > > insert_rows_
 

Additional Inherited Members

- Public Types inherited from database::query_dialect
enum class  query_type {
  none , select , insert , update ,
  delete_query
}
 

Detailed Description

SQL dialect implementation for PostgreSQL, SQLite.

Definition at line 98 of file query_dialect.h.

Constructor & Destructor Documentation

◆ sql_dialect()

database::detail::sql_dialect::sql_dialect ( database_types db_type)
explicit

◆ ~sql_dialect()

database::detail::sql_dialect::~sql_dialect ( )
overridedefault

Member Function Documentation

◆ add_join()

void database::detail::sql_dialect::add_join ( const std::string & table,
const std::string & condition,
join_type type )
overridevirtual

Implements database::query_dialect.

Definition at line 74 of file query_dialect.cpp.

75 {
76 std::ostringstream oss;
77 oss << join_type_to_string(type) << " JOIN " << table << " ON " << condition;
78 joins_.push_back(oss.str());
79 }
std::string join_type_to_string(join_type type) const
std::vector< std::string > joins_

References join_type_to_string(), and joins_.

Here is the call graph for this function:

◆ add_order_by()

void database::detail::sql_dialect::add_order_by ( const std::string & column,
sort_order order )
overridevirtual

Implements database::query_dialect.

Definition at line 91 of file query_dialect.cpp.

92 {
93 std::ostringstream oss;
94 oss << column << " " << (order == sort_order::asc ? "ASC" : "DESC");
95 order_by_clauses_.push_back(oss.str());
96 }
std::vector< std::string > order_by_clauses_

References database::asc, and order_by_clauses_.

◆ add_where_condition() [1/2]

void database::detail::sql_dialect::add_where_condition ( const query_condition & condition)
overridevirtual

Implements database::query_dialect.

Definition at line 64 of file query_dialect.cpp.

65 {
66 where_conditions_.push_back(condition);
67 }
std::vector< query_condition > where_conditions_

References where_conditions_.

◆ add_where_condition() [2/2]

void database::detail::sql_dialect::add_where_condition ( const std::string & field,
const std::string & op,
const core::database_value & value )
overridevirtual

Implements database::query_dialect.

Definition at line 69 of file query_dialect.cpp.

70 {
71 where_conditions_.emplace_back(field, op, value);
72 }

References where_conditions_.

◆ build()

std::string database::detail::sql_dialect::build ( ) const
overridevirtual

Implements database::query_dialect.

Definition at line 151 of file query_dialect.cpp.

152 {
153 std::ostringstream oss;
154
155 switch (type_) {
157 oss << "SELECT ";
158 if (select_columns_.empty()) {
159 oss << "*";
160 } else {
161 for (size_t i = 0; i < select_columns_.size(); ++i) {
162 if (i > 0) oss << ", ";
164 }
165 }
166 if (!from_table_.empty()) {
167 oss << " FROM " << escape_identifier(from_table_);
168 }
169 break;
170
172 oss << "INSERT INTO " << escape_identifier(target_table_);
173 if (!insert_rows_.empty()) {
174 auto& first_row = insert_rows_[0];
175 oss << " (";
176 bool first = true;
177 for (const auto& pair : first_row) {
178 if (!first) oss << ", ";
179 oss << escape_identifier(pair.first);
180 first = false;
181 }
182 oss << ") VALUES ";
183 for (size_t i = 0; i < insert_rows_.size(); ++i) {
184 if (i > 0) oss << ", ";
185 oss << "(";
186 bool first_val = true;
187 for (const auto& pair : insert_rows_[i]) {
188 if (!first_val) oss << ", ";
189 oss << format_value(pair.second);
190 first_val = false;
191 }
192 oss << ")";
193 }
194 } else if (!set_data_.empty()) {
195 oss << " (";
196 bool first = true;
197 for (const auto& pair : set_data_) {
198 if (!first) oss << ", ";
199 oss << escape_identifier(pair.first);
200 first = false;
201 }
202 oss << ") VALUES (";
203 first = true;
204 for (const auto& pair : set_data_) {
205 if (!first) oss << ", ";
206 oss << format_value(pair.second);
207 first = false;
208 }
209 oss << ")";
210 }
211 break;
212
214 oss << "UPDATE " << escape_identifier(target_table_) << " SET ";
215 {
216 bool first = true;
217 for (const auto& pair : set_data_) {
218 if (!first) oss << ", ";
219 oss << escape_identifier(pair.first) << " = " << format_value(pair.second);
220 first = false;
221 }
222 }
223 break;
224
226 oss << "DELETE FROM " << escape_identifier(target_table_);
227 break;
228
229 default:
230 throw std::runtime_error("Invalid query type");
231 }
232
233 // Add JOINs
234 for (const auto& join : joins_) {
235 oss << " " << join;
236 }
237
238 // Add WHERE clause
239 if (!where_conditions_.empty()) {
240 oss << " WHERE ";
241 for (size_t i = 0; i < where_conditions_.size(); ++i) {
242 if (i > 0) oss << " AND ";
243 oss << where_conditions_[i].to_sql();
244 }
245 }
246
247 // Add GROUP BY
248 if (!group_by_columns_.empty()) {
249 oss << " GROUP BY ";
250 for (size_t i = 0; i < group_by_columns_.size(); ++i) {
251 if (i > 0) oss << ", ";
253 }
254 }
255
256 // Add HAVING
257 if (!having_clause_.empty()) {
258 oss << " HAVING " << having_clause_;
259 }
260
261 // Add ORDER BY
262 if (!order_by_clauses_.empty()) {
263 oss << " ORDER BY ";
264 for (size_t i = 0; i < order_by_clauses_.size(); ++i) {
265 if (i > 0) oss << ", ";
266 oss << order_by_clauses_[i];
267 }
268 }
269
270 // Add LIMIT and OFFSET
271 if (limit_count_ > 0) {
272 oss << " LIMIT " << limit_count_;
273 }
274 if (offset_count_ > 0) {
275 oss << " OFFSET " << offset_count_;
276 }
277
278 return oss.str();
279 }
std::string escape_identifier(const std::string &identifier) const
std::vector< std::string > select_columns_
std::vector< std::map< std::string, core::database_value > > insert_rows_
std::map< std::string, core::database_value > set_data_
std::string format_value(const core::database_value &value) const
std::vector< std::string > group_by_columns_

References database::query_dialect::delete_query, escape_identifier(), format_value(), from_table_, group_by_columns_, having_clause_, database::query_dialect::insert, insert_rows_, joins_, limit_count_, offset_count_, order_by_clauses_, database::query_dialect::select, select_columns_, set_data_, target_table_, type_, database::query_dialect::update, and where_conditions_.

Here is the call graph for this function:

◆ escape_identifier()

std::string database::detail::sql_dialect::escape_identifier ( const std::string & identifier) const
private

Definition at line 303 of file query_dialect.cpp.

304 {
305 switch (db_type_) {
307 return "\"" + identifier + "\"";
309 return "[" + identifier + "]";
310 default:
311 return identifier;
312 }
313 }
@ sqlite
Indicates a SQLite database.
@ postgres
Indicates a PostgreSQL database.

References db_type_, database::postgres, and database::sqlite.

Referenced by build().

Here is the caller graph for this function:

◆ format_value()

std::string database::detail::sql_dialect::format_value ( const core::database_value & value) const
private

Definition at line 315 of file query_dialect.cpp.

316 {
317 std::ostringstream oss;
318 std::visit([&oss](const auto& val) {
319 using T = std::decay_t<decltype(val)>;
320 if constexpr (std::is_same_v<T, std::string>) {
321 // Escape single quotes by doubling them (SQL standard)
322 std::string escaped;
323 escaped.reserve(val.size() + 10);
324 for (char c : val) {
325 if (c == '\'') {
326 escaped += "''";
327 } else {
328 escaped += c;
329 }
330 }
331 oss << "'" << escaped << "'";
332 } else if constexpr (std::is_same_v<T, int64_t>) {
333 oss << val;
334 } else if constexpr (std::is_same_v<T, double>) {
335 oss << val;
336 } else if constexpr (std::is_same_v<T, bool>) {
337 oss << (val ? "TRUE" : "FALSE");
338 } else if constexpr (std::is_same_v<T, std::monostate> || std::is_same_v<T, std::nullptr_t>) {
339 oss << "NULL";
340 }
341 }, value);
342 return oss.str();
343 }

Referenced by build().

Here is the caller graph for this function:

◆ get_database_type()

database_types database::detail::sql_dialect::get_database_type ( ) const
overridevirtual

Implements database::query_dialect.

Definition at line 298 of file query_dialect.cpp.

299 {
300 return db_type_;
301 }

References db_type_.

◆ get_query_type()

query_dialect::query_type database::detail::sql_dialect::get_query_type ( ) const
overridevirtual

Implements database::query_dialect.

Definition at line 48 of file query_dialect.cpp.

49 {
50 return type_;
51 }

References type_.

◆ join_type_to_string()

std::string database::detail::sql_dialect::join_type_to_string ( join_type type) const
private

Definition at line 345 of file query_dialect.cpp.

346 {
347 switch (type) {
348 case join_type::inner: return "INNER";
349 case join_type::left: return "LEFT";
350 case join_type::right: return "RIGHT";
351 case join_type::full_outer: return "FULL OUTER";
352 case join_type::cross: return "CROSS";
353 default: return "INNER";
354 }
355 }

References database::cross, database::full_outer, database::inner, database::left, and database::right.

Referenced by add_join().

Here is the caller graph for this function:

◆ reset()

void database::detail::sql_dialect::reset ( )
overridevirtual

◆ set_collection()

void database::detail::sql_dialect::set_collection ( const std::string & name)
overridevirtual

Implements database::query_dialect.

Definition at line 141 of file query_dialect.cpp.

142 {
143 // No-op for SQL
144 }

◆ set_delete_table()

void database::detail::sql_dialect::set_delete_table ( const std::string & table)
overridevirtual

Implements database::query_dialect.

Definition at line 135 of file query_dialect.cpp.

136 {
138 target_table_ = table;
139 }

References database::query_dialect::delete_query, target_table_, and type_.

◆ set_from_table()

void database::detail::sql_dialect::set_from_table ( const std::string & table)
overridevirtual

Implements database::query_dialect.

Definition at line 59 of file query_dialect.cpp.

60 {
61 from_table_ = table;
62 }

References from_table_.

◆ set_group_by()

void database::detail::sql_dialect::set_group_by ( const std::vector< std::string > & columns)
overridevirtual

Implements database::query_dialect.

Definition at line 81 of file query_dialect.cpp.

82 {
83 group_by_columns_ = columns;
84 }

References group_by_columns_.

◆ set_having()

void database::detail::sql_dialect::set_having ( const std::string & condition)
overridevirtual

Implements database::query_dialect.

Definition at line 86 of file query_dialect.cpp.

87 {
88 having_clause_ = condition;
89 }

References having_clause_.

◆ set_insert_data()

void database::detail::sql_dialect::set_insert_data ( const std::map< std::string, core::database_value > & data)
overridevirtual

Implements database::query_dialect.

Definition at line 114 of file query_dialect.cpp.

115 {
116 set_data_ = data;
117 }

References set_data_.

◆ set_insert_rows()

void database::detail::sql_dialect::set_insert_rows ( const std::vector< std::map< std::string, core::database_value > > & rows)
overridevirtual

Implements database::query_dialect.

Definition at line 119 of file query_dialect.cpp.

120 {
121 insert_rows_ = rows;
122 }

References insert_rows_.

◆ set_insert_table()

void database::detail::sql_dialect::set_insert_table ( const std::string & table)
overridevirtual

Implements database::query_dialect.

Definition at line 108 of file query_dialect.cpp.

109 {
111 target_table_ = table;
112 }

References database::query_dialect::insert, target_table_, and type_.

◆ set_key()

void database::detail::sql_dialect::set_key ( const std::string & key)
overridevirtual

Implements database::query_dialect.

Definition at line 146 of file query_dialect.cpp.

147 {
148 // No-op for SQL
149 }

◆ set_limit()

void database::detail::sql_dialect::set_limit ( size_t count)
overridevirtual

Implements database::query_dialect.

Definition at line 98 of file query_dialect.cpp.

99 {
100 limit_count_ = count;
101 }

References limit_count_.

◆ set_offset()

void database::detail::sql_dialect::set_offset ( size_t count)
overridevirtual

Implements database::query_dialect.

Definition at line 103 of file query_dialect.cpp.

104 {
105 offset_count_ = count;
106 }

References offset_count_.

◆ set_query_type()

void database::detail::sql_dialect::set_query_type ( query_type type)
overridevirtual

Implements database::query_dialect.

Definition at line 43 of file query_dialect.cpp.

44 {
45 type_ = type;
46 }

References type_.

◆ set_select_columns()

void database::detail::sql_dialect::set_select_columns ( const std::vector< std::string > & columns)
overridevirtual

Implements database::query_dialect.

Definition at line 53 of file query_dialect.cpp.

54 {
56 select_columns_ = columns;
57 }

References database::query_dialect::select, select_columns_, and type_.

◆ set_update_data()

void database::detail::sql_dialect::set_update_data ( const std::map< std::string, core::database_value > & data)
overridevirtual

Implements database::query_dialect.

Definition at line 130 of file query_dialect.cpp.

131 {
132 set_data_ = data;
133 }

References set_data_.

◆ set_update_table()

void database::detail::sql_dialect::set_update_table ( const std::string & table)
overridevirtual

Implements database::query_dialect.

Definition at line 124 of file query_dialect.cpp.

125 {
127 target_table_ = table;
128 }

References target_table_, type_, and database::query_dialect::update.

Member Data Documentation

◆ db_type_

database_types database::detail::sql_dialect::db_type_
private

Definition at line 142 of file query_dialect.h.

Referenced by escape_identifier(), and get_database_type().

◆ from_table_

std::string database::detail::sql_dialect::from_table_
private

Definition at line 145 of file query_dialect.h.

Referenced by build(), reset(), and set_from_table().

◆ group_by_columns_

std::vector<std::string> database::detail::sql_dialect::group_by_columns_
private

Definition at line 148 of file query_dialect.h.

Referenced by build(), reset(), and set_group_by().

◆ having_clause_

std::string database::detail::sql_dialect::having_clause_
private

Definition at line 149 of file query_dialect.h.

Referenced by build(), reset(), and set_having().

◆ insert_rows_

std::vector<std::map<std::string, core::database_value> > database::detail::sql_dialect::insert_rows_
private

Definition at line 156 of file query_dialect.h.

Referenced by build(), reset(), and set_insert_rows().

◆ joins_

std::vector<std::string> database::detail::sql_dialect::joins_
private

Definition at line 147 of file query_dialect.h.

Referenced by add_join(), build(), and reset().

◆ limit_count_

size_t database::detail::sql_dialect::limit_count_
private

Definition at line 151 of file query_dialect.h.

Referenced by build(), reset(), and set_limit().

◆ offset_count_

size_t database::detail::sql_dialect::offset_count_
private

Definition at line 152 of file query_dialect.h.

Referenced by build(), reset(), and set_offset().

◆ order_by_clauses_

std::vector<std::string> database::detail::sql_dialect::order_by_clauses_
private

Definition at line 150 of file query_dialect.h.

Referenced by add_order_by(), build(), and reset().

◆ select_columns_

std::vector<std::string> database::detail::sql_dialect::select_columns_
private

Definition at line 144 of file query_dialect.h.

Referenced by build(), reset(), and set_select_columns().

◆ set_data_

std::map<std::string, core::database_value> database::detail::sql_dialect::set_data_
private

Definition at line 155 of file query_dialect.h.

Referenced by build(), reset(), set_insert_data(), and set_update_data().

◆ target_table_

std::string database::detail::sql_dialect::target_table_
private

Definition at line 154 of file query_dialect.h.

Referenced by build(), reset(), set_delete_table(), set_insert_table(), and set_update_table().

◆ type_

query_type database::detail::sql_dialect::type_
private

◆ where_conditions_

std::vector<query_condition> database::detail::sql_dialect::where_conditions_
private

Definition at line 146 of file query_dialect.h.

Referenced by add_where_condition(), add_where_condition(), build(), and reset().


The documentation for this class was generated from the following files: