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

Thread-safe immutable query builder using functional programming style. More...

#include <immutable_query_builder.h>

Collaboration diagram for database::immutable_query_builder:
Collaboration graph

Public Member Functions

 immutable_query_builder (const std::string &table)
 Constructs a new immutable query builder.
 
immutable_query_builder select (std::vector< std::string > fields) const
 SELECT clause - specifies which columns to select.
 
immutable_query_builder where (const std::string &field, const std::string &op, const core::database_value &value) const
 WHERE clause - adds a condition.
 
immutable_query_builder where (const query_condition &condition) const
 WHERE clause - adds a query_condition.
 
immutable_query_builder order_by (const std::string &field, sort_order order=sort_order::asc) const
 ORDER BY clause - specifies sorting.
 
immutable_query_builder limit (uint32_t count) const
 LIMIT clause - limits number of results.
 
immutable_query_builder offset (uint32_t count) const
 OFFSET clause - skips rows.
 
immutable_query_builder join (const std::string &table, const std::string &condition, join_type type=join_type::inner) const
 JOIN clause - adds a join.
 
immutable_query_builder group_by (std::vector< std::string > fields) const
 GROUP BY clause - groups results.
 
immutable_query_builder having (const std::string &condition) const
 HAVING clause - filters grouped results.
 
std::string build () const
 Builds the final SQL query string.
 
std::string build_for_database (database_types db_type) const
 Builds the SQL query for a specific database type.
 

Private Member Functions

 immutable_query_builder (std::string table, std::vector< std::string > select_fields, std::vector< query_condition > conditions, std::vector< std::pair< std::string, sort_order > > order_by, std::optional< uint32_t > limit, std::optional< uint32_t > offset, std::vector< std::tuple< std::string, std::string, join_type > > joins, std::vector< std::string > group_by_fields, std::string having_clause)
 
std::string escape_identifier (const std::string &identifier, database_types db_type) const
 
std::string format_value (const core::database_value &value, database_types db_type) const
 
std::string join_type_to_string (join_type type) const
 

Private Attributes

const std::string table_
 
const std::vector< std::string > select_fields_
 
const std::vector< query_conditionconditions_
 
const std::vector< std::pair< std::string, sort_order > > order_by_
 
const std::optional< uint32_t > limit_
 
const std::optional< uint32_t > offset_
 
const std::vector< std::tuple< std::string, std::string, join_type > > joins_
 
const std::vector< std::string > group_by_fields_
 
const std::string having_clause_
 

Detailed Description

Thread-safe immutable query builder using functional programming style.

Thread Safety

  • FULLY thread-safe. All methods are const and return new instances.
  • No mutable state. All fields are const.
  • Safe to share instances across threads.
  • Immutable builder pattern ensures no race conditions.

Design

  • Each method returns a new instance with updated state.
  • Original instance remains unchanged.
  • Functional programming style (copy-on-write).
  • No locks needed due to immutability.

Usage Example

auto query = immutable_query_builder("users")
.select({"id", "name", "email"})
.where("active", "=", true)
.limit(10)
.build();
immutable_query_builder order_by(const std::string &field, sort_order order=sort_order::asc) const
ORDER BY clause - specifies sorting.
std::string build() const
Builds the final SQL query string.
immutable_query_builder where(const std::string &field, const std::string &op, const core::database_value &value) const
WHERE clause - adds a condition.
immutable_query_builder(const std::string &table)
Constructs a new immutable query builder.
immutable_query_builder limit(uint32_t count) const
LIMIT clause - limits number of results.

Definition at line 43 of file immutable_query_builder.h.

Constructor & Destructor Documentation

◆ immutable_query_builder() [1/2]

database::immutable_query_builder::immutable_query_builder ( const std::string & table)
explicit

Constructs a new immutable query builder.

Parameters
tableTable name for the query.

Definition at line 12 of file immutable_query_builder.cpp.

13 : table_(table)
15 , conditions_()
16 , order_by_()
17 , limit_(std::nullopt)
18 , offset_(std::nullopt)
19 , joins_()
22 {
23 }
const std::optional< uint32_t > limit_
const std::optional< uint32_t > offset_
const std::vector< std::tuple< std::string, std::string, join_type > > joins_
const std::vector< query_condition > conditions_
const std::vector< std::string > select_fields_
const std::vector< std::string > group_by_fields_
const std::vector< std::pair< std::string, sort_order > > order_by_

Referenced by group_by(), having(), join(), limit(), offset(), order_by(), select(), where(), and where().

Here is the caller graph for this function:

◆ immutable_query_builder() [2/2]

database::immutable_query_builder::immutable_query_builder ( std::string table,
std::vector< std::string > select_fields,
std::vector< query_condition > conditions,
std::vector< std::pair< std::string, sort_order > > order_by,
std::optional< uint32_t > limit,
std::optional< uint32_t > offset,
std::vector< std::tuple< std::string, std::string, join_type > > joins,
std::vector< std::string > group_by_fields,
std::string having_clause )
private

Definition at line 26 of file immutable_query_builder.cpp.

37 : table_(std::move(table))
38 , select_fields_(std::move(select_fields))
39 , conditions_(std::move(conditions))
40 , order_by_(std::move(order_by))
41 , limit_(limit)
43 , joins_(std::move(joins))
44 , group_by_fields_(std::move(group_by_fields))
45 , having_clause_(std::move(having_clause))
46 {
47 }
immutable_query_builder offset(uint32_t count) const
OFFSET clause - skips rows.

Member Function Documentation

◆ build()

std::string database::immutable_query_builder::build ( ) const

Builds the final SQL query string.

Returns
SQL query string.

Thread-safe: No state modification, all fields are const.

Definition at line 196 of file immutable_query_builder.cpp.

197 {
199 }
std::string build_for_database(database_types db_type) const
Builds the SQL query for a specific database type.
@ postgres
Indicates a PostgreSQL database.

References build_for_database(), and database::postgres.

Referenced by TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_for_database()

std::string database::immutable_query_builder::build_for_database ( database_types db_type) const

Builds the SQL query for a specific database type.

Parameters
db_typeDatabase type (PostgreSQL, SQLite, etc.).
Returns
SQL query string formatted for the specified database.

Definition at line 201 of file immutable_query_builder.cpp.

202 {
203 std::ostringstream query;
204
205 // SELECT clause
206 query << "SELECT ";
207 if (select_fields_.empty())
208 {
209 query << "*";
210 }
211 else
212 {
213 for (size_t i = 0; i < select_fields_.size(); ++i)
214 {
215 if (i > 0)
216 query << ", ";
217 query << escape_identifier(select_fields_[i], db_type);
218 }
219 }
220
221 // FROM clause
222 query << " FROM " << escape_identifier(table_, db_type);
223
224 // JOIN clauses
225 for (const auto& [join_table, join_condition, join_type_val] : joins_)
226 {
227 query << " " << join_type_to_string(join_type_val) << " JOIN "
228 << escape_identifier(join_table, db_type)
229 << " ON " << join_condition;
230 }
231
232 // WHERE clause
233 if (!conditions_.empty())
234 {
235 query << " WHERE ";
236 for (size_t i = 0; i < conditions_.size(); ++i)
237 {
238 if (i > 0)
239 query << " AND ";
240 query << conditions_[i].to_sql();
241 }
242 }
243
244 // GROUP BY clause
245 if (!group_by_fields_.empty())
246 {
247 query << " GROUP BY ";
248 for (size_t i = 0; i < group_by_fields_.size(); ++i)
249 {
250 if (i > 0)
251 query << ", ";
252 query << escape_identifier(group_by_fields_[i], db_type);
253 }
254 }
255
256 // HAVING clause
257 if (!having_clause_.empty())
258 {
259 query << " HAVING " << having_clause_;
260 }
261
262 // ORDER BY clause
263 if (!order_by_.empty())
264 {
265 query << " ORDER BY ";
266 for (size_t i = 0; i < order_by_.size(); ++i)
267 {
268 if (i > 0)
269 query << ", ";
270 query << escape_identifier(order_by_[i].first, db_type) << " "
271 << (order_by_[i].second == sort_order::asc ? "ASC" : "DESC");
272 }
273 }
274
275 // LIMIT clause
276 if (limit_.has_value())
277 {
278 query << " LIMIT " << limit_.value();
279 }
280
281 // OFFSET clause
282 if (offset_.has_value())
283 {
284 query << " OFFSET " << offset_.value();
285 }
286
287 return query.str();
288 }
std::string join_type_to_string(join_type type) const
std::string escape_identifier(const std::string &identifier, database_types db_type) const

References database::asc, conditions_, escape_identifier(), group_by_fields_, having_clause_, join_type_to_string(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Referenced by build().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ escape_identifier()

std::string database::immutable_query_builder::escape_identifier ( const std::string & identifier,
database_types db_type ) const
private

Definition at line 290 of file immutable_query_builder.cpp.

291 {
292 switch (db_type)
293 {
295 return "\"" + identifier + "\"";
297 return "\"" + identifier + "\"";
298 default:
299 return identifier;
300 }
301 }
@ sqlite
Indicates a SQLite database.

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

Referenced by build_for_database().

Here is the caller graph for this function:

◆ format_value()

std::string database::immutable_query_builder::format_value ( const core::database_value & value,
database_types db_type ) const
private

Definition at line 303 of file immutable_query_builder.cpp.

304 {
305 if (std::holds_alternative<std::string>(value))
306 {
307 const auto& str = std::get<std::string>(value);
308 std::string escaped;
309 escaped.reserve(str.size() + 2);
310 escaped += "'";
311 for (char c : str)
312 {
313 if (c == '\'')
314 escaped += "''";
315 else
316 escaped += c;
317 }
318 escaped += "'";
319 return escaped;
320 }
321 else if (std::holds_alternative<int64_t>(value))
322 {
323 return std::to_string(std::get<int64_t>(value));
324 }
325 else if (std::holds_alternative<double>(value))
326 {
327 return std::to_string(std::get<double>(value));
328 }
329 else if (std::holds_alternative<bool>(value))
330 {
331 return std::get<bool>(value) ? "TRUE" : "FALSE";
332 }
333 else if (std::holds_alternative<std::nullptr_t>(value))
334 {
335 return "NULL";
336 }
337 return "NULL";
338 }

◆ group_by()

immutable_query_builder database::immutable_query_builder::group_by ( std::vector< std::string > fields) const

GROUP BY clause - groups results.

Parameters
fieldsFields to group by.
Returns
New immutable_query_builder instance with updated grouping.

Definition at line 166 of file immutable_query_builder.cpp.

167 {
169 table_,
172 order_by_,
173 limit_,
174 offset_,
175 joins_,
176 std::move(fields),
178 );
179 }

References conditions_, having_clause_, immutable_query_builder(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ having()

immutable_query_builder database::immutable_query_builder::having ( const std::string & condition) const

HAVING clause - filters grouped results.

Parameters
conditionCondition for filtering groups.
Returns
New immutable_query_builder instance with updated having clause.

Definition at line 181 of file immutable_query_builder.cpp.

182 {
184 table_,
187 order_by_,
188 limit_,
189 offset_,
190 joins_,
192 condition
193 );
194 }

References conditions_, group_by_fields_, immutable_query_builder(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ join()

immutable_query_builder database::immutable_query_builder::join ( const std::string & table,
const std::string & condition,
join_type type = join_type::inner ) const

JOIN clause - adds a join.

Parameters
tableTable to join.
conditionJoin condition.
typeJoin type (inner, left, right, etc.).
Returns
New immutable_query_builder instance with updated join.

Definition at line 148 of file immutable_query_builder.cpp.

149 {
150 auto new_joins = joins_;
151 new_joins.emplace_back(table, condition, type);
152
154 table_,
157 order_by_,
158 limit_,
159 offset_,
160 std::move(new_joins),
163 );
164 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ join_type_to_string()

std::string database::immutable_query_builder::join_type_to_string ( join_type type) const
private

Definition at line 340 of file immutable_query_builder.cpp.

341 {
342 switch (type)
343 {
344 case join_type::inner:
345 return "INNER";
346 case join_type::left:
347 return "LEFT";
348 case join_type::right:
349 return "RIGHT";
351 return "FULL OUTER";
352 case join_type::cross:
353 return "CROSS";
354 default:
355 return "INNER";
356 }
357 }

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

Referenced by build_for_database().

Here is the caller graph for this function:

◆ limit()

immutable_query_builder database::immutable_query_builder::limit ( uint32_t count) const

LIMIT clause - limits number of results.

Parameters
countMaximum number of rows to return.
Returns
New immutable_query_builder instance with updated limit.

Definition at line 118 of file immutable_query_builder.cpp.

119 {
121 table_,
124 order_by_,
125 count,
126 offset_,
127 joins_,
130 );
131 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ offset()

immutable_query_builder database::immutable_query_builder::offset ( uint32_t count) const

OFFSET clause - skips rows.

Parameters
countNumber of rows to skip.
Returns
New immutable_query_builder instance with updated offset.

Definition at line 133 of file immutable_query_builder.cpp.

134 {
136 table_,
139 order_by_,
140 limit_,
141 count,
142 joins_,
145 );
146 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, limit_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ order_by()

immutable_query_builder database::immutable_query_builder::order_by ( const std::string & field,
sort_order order = sort_order::asc ) const

ORDER BY clause - specifies sorting.

Parameters
fieldField name to sort by.
orderSort order (asc or desc).
Returns
New immutable_query_builder instance with updated order.

Definition at line 100 of file immutable_query_builder.cpp.

101 {
102 auto new_order_by = order_by_;
103 new_order_by.emplace_back(field, order);
104
106 table_,
109 std::move(new_order_by),
110 limit_,
111 offset_,
112 joins_,
115 );
116 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ select()

immutable_query_builder database::immutable_query_builder::select ( std::vector< std::string > fields) const

SELECT clause - specifies which columns to select.

Parameters
fieldsVector of column names to select.
Returns
New immutable_query_builder instance with updated select fields.

Definition at line 49 of file immutable_query_builder.cpp.

50 {
52 table_,
53 std::move(fields),
56 limit_,
57 offset_,
58 joins_,
61 );
62 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, limit_, offset_, order_by_, and table_.

Here is the call graph for this function:

◆ where() [1/2]

immutable_query_builder database::immutable_query_builder::where ( const query_condition & condition) const

WHERE clause - adds a query_condition.

Parameters
conditionPre-built query_condition.
Returns
New immutable_query_builder instance with updated conditions.

Definition at line 82 of file immutable_query_builder.cpp.

83 {
84 auto new_conditions = conditions_;
85 new_conditions.push_back(condition);
86
88 table_,
90 std::move(new_conditions),
92 limit_,
93 offset_,
94 joins_,
97 );
98 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

◆ where() [2/2]

immutable_query_builder database::immutable_query_builder::where ( const std::string & field,
const std::string & op,
const core::database_value & value ) const

WHERE clause - adds a condition.

Parameters
fieldField name.
opOperator (e.g., "=", ">", "<", "LIKE").
valueValue to compare against.
Returns
New immutable_query_builder instance with updated conditions.

Definition at line 64 of file immutable_query_builder.cpp.

65 {
66 auto new_conditions = conditions_;
67 new_conditions.emplace_back(field, op, value);
68
70 table_,
72 std::move(new_conditions),
74 limit_,
75 offset_,
76 joins_,
79 );
80 }

References conditions_, group_by_fields_, having_clause_, immutable_query_builder(), joins_, limit_, offset_, order_by_, select_fields_, and table_.

Here is the call graph for this function:

Member Data Documentation

◆ conditions_

const std::vector<query_condition> database::immutable_query_builder::conditions_
private

◆ group_by_fields_

const std::vector<std::string> database::immutable_query_builder::group_by_fields_
private

◆ having_clause_

const std::string database::immutable_query_builder::having_clause_
private

◆ joins_

const std::vector<std::tuple<std::string, std::string, join_type> > database::immutable_query_builder::joins_
private

◆ limit_

const std::optional<uint32_t> database::immutable_query_builder::limit_
private

◆ offset_

const std::optional<uint32_t> database::immutable_query_builder::offset_
private

◆ order_by_

const std::vector<std::pair<std::string, sort_order> > database::immutable_query_builder::order_by_
private

◆ select_fields_

const std::vector<std::string> database::immutable_query_builder::select_fields_
private

◆ table_

const std::string database::immutable_query_builder::table_
private

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