relx 0.1.0
A Modern C++23 Type-Safe SQL Query Builder
Loading...
Searching...
No Matches
arithmetic.hpp
Go to the documentation of this file.
1#pragma once
2
4#include "core.hpp"
5#include "operators.hpp"
6#include "schema_adapter.hpp"
7#include "value.hpp"
8
9#include <type_traits>
10
11namespace relx::query {
12
14namespace arithmetic_checking {
15
17template <typename T>
18concept Arithmetic = std::is_arithmetic_v<std::remove_cvref_t<T>> &&
19 !std::same_as<std::remove_cvref_t<T>, bool>;
20
22template <typename T>
24 using type = T;
25};
26
27template <typename TableT, schema::fixed_string Name, typename ColumnT, typename... Modifiers>
28struct extract_arithmetic_type<schema::column<TableT, Name, ColumnT, Modifiers...>> {
29 using type = ColumnT;
30};
31
32template <typename T>
34
36template <typename T>
38 using type = T;
39};
40
41template <typename T>
42struct remove_optional<std::optional<T>> {
43 using type = T;
44};
45
46template <typename T>
48
50inline constexpr std::string_view arithmetic_error_message =
51 "Arithmetic operations (+, -, *, /) can only be performed on numeric columns (int, long, "
52 "float, double, etc.). "
53 "String, boolean, and other non-numeric types cannot be used in arithmetic expressions.";
54} // namespace arithmetic_checking
55
57template <SqlExpr Left, SqlExpr Right>
59public:
60 ArithmeticExpr(Left left, std::string op, Right right)
61 : left_(std::move(left)), op_(std::move(op)), right_(std::move(right)) {}
62
63 std::string to_sql() const override {
64 return "(" + left_.to_sql() + " " + op_ + " " + right_.to_sql() + ")";
65 }
66
67 std::vector<std::string> bind_params() const override {
68 auto left_params = left_.bind_params();
69 auto right_params = right_.bind_params();
70 left_params.insert(left_params.end(), right_params.begin(), right_params.end());
71 return left_params;
72 }
73
74 std::string column_name() const override {
75 std::string left_name;
76 std::string right_name;
77
78 // Get column names, handling both ColumnExpression and other SqlExpr types
79 if constexpr (std::is_base_of_v<ColumnExpression, Left>) {
80 left_name = left_.column_name();
81 } else {
82 left_name = "expr";
83 }
84
85 if constexpr (std::is_base_of_v<ColumnExpression, Right>) {
86 right_name = right_.column_name();
87 } else {
88 right_name = "expr";
89 }
90
91 return "(" + left_name + "_" + op_ + "_" + right_name + ")";
92 }
93
94 std::string table_name() const override {
95 // For arithmetic expressions, return the table name of the first operand that has one
96 if constexpr (std::is_base_of_v<ColumnExpression, Left>) {
97 auto table = left_.table_name();
98 if (!table.empty()) {
99 return table;
100 }
101 }
102 if constexpr (std::is_base_of_v<ColumnExpression, Right>) {
103 return right_.table_name();
104 }
105 return "";
106 }
107
108private:
109 Left left_;
110 std::string op_;
111 Right right_;
112};
113
115template <typename TableT1, schema::fixed_string Name1, typename T1, typename... Modifiers1,
116 typename TableT2, schema::fixed_string Name2, typename T2, typename... Modifiers2>
119 // Extract base types, removing optional wrapper if present
121 using RightBaseType = arithmetic_checking::remove_optional_t<T2>;
122
127
128 auto left_expr = to_expr(left);
129 auto right_expr = to_expr(right);
130 return ArithmeticExpr<decltype(left_expr), decltype(right_expr)>(std::move(left_expr), "+",
131 std::move(right_expr));
132}
133
135template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
136 typename ValueT>
137 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
142 static_assert(
144 "Arithmetic operations require numeric values. Cannot add non-numeric values to columns.");
145
146 auto left_expr = to_expr(left);
147 auto value_expr = val(std::forward<ValueT>(value));
148 return ArithmeticExpr<decltype(left_expr), decltype(value_expr)>(std::move(left_expr), "+",
149 std::move(value_expr));
150}
151
153template <typename ValueT, typename TableT, schema::fixed_string Name, typename T,
154 typename... Modifiers>
155 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
157 return right + std::forward<ValueT>(value);
158}
159
161template <typename TableT1, schema::fixed_string Name1, typename T1, typename... Modifiers1,
162 typename TableT2, schema::fixed_string Name2, typename T2, typename... Modifiers2>
178
180template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
181 typename ValueT>
182 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
188 "Arithmetic operations require numeric values. Cannot subtract non-numeric values "
189 "from columns.");
190
191 auto left_expr = to_expr(left);
192 auto value_expr = val(std::forward<ValueT>(value));
193 return ArithmeticExpr<decltype(left_expr), decltype(value_expr)>(std::move(left_expr), "-",
194 std::move(value_expr));
195}
196
198template <typename ValueT, typename TableT, schema::fixed_string Name, typename T,
199 typename... Modifiers>
200 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
202 using RightBaseType = arithmetic_checking::remove_optional_t<T>;
206 "Arithmetic operations require numeric values.");
207
208 auto value_expr = val(std::forward<ValueT>(value));
209 auto right_expr = to_expr(right);
210 return ArithmeticExpr<decltype(value_expr), decltype(right_expr)>(std::move(value_expr), "-",
211 std::move(right_expr));
212}
213
215template <typename TableT1, schema::fixed_string Name1, typename T1, typename... Modifiers1,
216 typename TableT2, schema::fixed_string Name2, typename T2, typename... Modifiers2>
232
234template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
235 typename ValueT>
236 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
242 "Arithmetic operations require numeric values. Cannot multiply columns by "
243 "non-numeric values.");
244
245 auto left_expr = to_expr(left);
246 auto value_expr = val(std::forward<ValueT>(value));
247 return ArithmeticExpr<decltype(left_expr), decltype(value_expr)>(std::move(left_expr), "*",
248 std::move(value_expr));
249}
250
252template <typename ValueT, typename TableT, schema::fixed_string Name, typename T,
253 typename... Modifiers>
254 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
256 return right * std::forward<ValueT>(value);
257}
258
260template <typename TableT1, schema::fixed_string Name1, typename T1, typename... Modifiers1,
261 typename TableT2, schema::fixed_string Name2, typename T2, typename... Modifiers2>
277
279template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
280 typename ValueT>
281 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
286 static_assert(
288 "Arithmetic operations require numeric values. Cannot divide columns by non-numeric values.");
289
290 auto left_expr = to_expr(left);
291 auto value_expr = val(std::forward<ValueT>(value));
292 return ArithmeticExpr<decltype(left_expr), decltype(value_expr)>(std::move(left_expr), "/",
293 std::move(value_expr));
294}
295
297template <typename ValueT, typename TableT, schema::fixed_string Name, typename T,
298 typename... Modifiers>
299 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
301 using RightBaseType = arithmetic_checking::remove_optional_t<T>;
305 "Arithmetic operations require numeric values.");
306
307 auto value_expr = val(std::forward<ValueT>(value));
308 auto right_expr = to_expr(right);
309 return ArithmeticExpr<decltype(value_expr), decltype(right_expr)>(std::move(value_expr), "/",
310 std::move(right_expr));
311}
312
313// Arithmetic operators for ArithmeticExpr to support chaining
314
316template <SqlExpr Left, SqlExpr Right, typename TableT, schema::fixed_string Name, typename T,
317 typename... Modifiers>
320 using RightBaseType = arithmetic_checking::remove_optional_t<T>;
323
324 auto right_expr = to_expr(right);
325 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(right_expr)>(left_expr, "+",
326 std::move(right_expr));
327}
328
330template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
331 SqlExpr Left, SqlExpr Right>
333 const ArithmeticExpr<Left, Right>& right_expr) {
337
338 auto left_expr = to_expr(left);
339 return ArithmeticExpr<decltype(left_expr), ArithmeticExpr<Left, Right>>(std::move(left_expr), "+",
340 right_expr);
341}
342
344template <SqlExpr Left, SqlExpr Right, typename ValueT>
345 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
346auto operator+(const ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
348 "Arithmetic operations require numeric values.");
349
350 auto value_expr = val(std::forward<ValueT>(value));
351 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(value_expr)>(left_expr, "+",
352 std::move(value_expr));
353}
354
356template <typename ValueT, SqlExpr Left, SqlExpr Right>
357 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
358auto operator+(ValueT&& value, const ArithmeticExpr<Left, Right>& right_expr) {
359 return right_expr + std::forward<ValueT>(value);
360}
361
363template <SqlExpr Left, SqlExpr Right, typename TableT, schema::fixed_string Name, typename T,
364 typename... Modifiers>
367 using RightBaseType = arithmetic_checking::remove_optional_t<T>;
370
371 auto right_expr = to_expr(right);
372 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(right_expr)>(left_expr, "-",
373 std::move(right_expr));
374}
375
377template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
378 SqlExpr Left, SqlExpr Right>
380 const ArithmeticExpr<Left, Right>& right_expr) {
384
385 auto left_expr = to_expr(left);
386 return ArithmeticExpr<decltype(left_expr), ArithmeticExpr<Left, Right>>(std::move(left_expr), "-",
387 right_expr);
388}
389
391template <SqlExpr Left, SqlExpr Right, typename ValueT>
392 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
393auto operator-(const ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
395 "Arithmetic operations require numeric values.");
396
397 auto value_expr = val(std::forward<ValueT>(value));
398 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(value_expr)>(left_expr, "-",
399 std::move(value_expr));
400}
401
403template <typename ValueT, SqlExpr Left, SqlExpr Right>
404 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
405auto operator-(ValueT&& value, const ArithmeticExpr<Left, Right>& right_expr) {
407 "Arithmetic operations require numeric values.");
408
409 auto value_expr = val(std::forward<ValueT>(value));
410 return ArithmeticExpr<decltype(value_expr), ArithmeticExpr<Left, Right>>(std::move(value_expr),
411 "-", right_expr);
412}
413
415template <SqlExpr Left, SqlExpr Right, typename TableT, schema::fixed_string Name, typename T,
416 typename... Modifiers>
419 using RightBaseType = arithmetic_checking::remove_optional_t<T>;
422
423 auto right_expr = to_expr(right);
424 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(right_expr)>(left_expr, "*",
425 std::move(right_expr));
426}
427
429template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
430 SqlExpr Left, SqlExpr Right>
432 const ArithmeticExpr<Left, Right>& right_expr) {
436
437 auto left_expr = to_expr(left);
438 return ArithmeticExpr<decltype(left_expr), ArithmeticExpr<Left, Right>>(std::move(left_expr), "*",
439 right_expr);
440}
441
443template <SqlExpr Left, SqlExpr Right, typename ValueT>
444 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
445auto operator*(const ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
447 "Arithmetic operations require numeric values.");
448
449 auto value_expr = val(std::forward<ValueT>(value));
450 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(value_expr)>(left_expr, "*",
451 std::move(value_expr));
452}
453
455template <typename ValueT, SqlExpr Left, SqlExpr Right>
456 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
457auto operator*(ValueT&& value, const ArithmeticExpr<Left, Right>& right_expr) {
458 return right_expr * std::forward<ValueT>(value);
459}
460
462template <SqlExpr Left, SqlExpr Right, typename TableT, schema::fixed_string Name, typename T,
463 typename... Modifiers>
466 using RightBaseType = arithmetic_checking::remove_optional_t<T>;
469
470 auto right_expr = to_expr(right);
471 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(right_expr)>(left_expr, "/",
472 std::move(right_expr));
473}
474
476template <typename TableT, schema::fixed_string Name, typename T, typename... Modifiers,
477 SqlExpr Left, SqlExpr Right>
479 const ArithmeticExpr<Left, Right>& right_expr) {
483
484 auto left_expr = to_expr(left);
485 return ArithmeticExpr<decltype(left_expr), ArithmeticExpr<Left, Right>>(std::move(left_expr), "/",
486 right_expr);
487}
488
490template <SqlExpr Left, SqlExpr Right, typename ValueT>
491 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
492auto operator/(const ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
494 "Arithmetic operations require numeric values.");
495
496 auto value_expr = val(std::forward<ValueT>(value));
497 return ArithmeticExpr<ArithmeticExpr<Left, Right>, decltype(value_expr)>(left_expr, "/",
498 std::move(value_expr));
499}
500
502template <typename ValueT, SqlExpr Left, SqlExpr Right>
503 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
504auto operator/(ValueT&& value, const query::ArithmeticExpr<Left, Right>& right_expr) {
506 "Arithmetic operations require numeric values.");
507
508 auto value_expr = query::val(std::forward<ValueT>(value));
510 std::move(value_expr), "/", std::move(right_expr));
511}
512
513} // namespace relx::query
514
515// Arithmetic operators need to be in the schema namespace for ADL to find them
516namespace relx::schema {
517
519template <typename TableT1, fixed_string Name1, typename T1, typename... Modifiers1,
520 typename TableT2, fixed_string Name2, typename T2, typename... Modifiers2>
521auto operator+(const column<TableT1, Name1, T1, Modifiers1...>& left,
523 // Extract base types, removing optional wrapper if present
526
531
532 auto left_expr = query::to_expr(left);
533 auto right_expr = query::to_expr(right);
535 std::move(right_expr));
536}
537
539template <typename TableT, fixed_string Name, typename T, typename... Modifiers, typename ValueT>
540 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
541auto operator+(const column<TableT, Name, T, Modifiers...>& left, ValueT&& value) {
545 static_assert(
547 "Arithmetic operations require numeric values. Cannot add non-numeric values to columns.");
548
549 auto left_expr = query::to_expr(left);
550 auto value_expr = query::val(std::forward<ValueT>(value));
552 std::move(value_expr));
553}
554
556template <typename ValueT, typename TableT, fixed_string Name, typename T, typename... Modifiers>
557 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
558auto operator+(ValueT&& value, const column<TableT, Name, T, Modifiers...>& right) {
559 return right + std::forward<ValueT>(value);
560}
561
563template <typename TableT1, fixed_string Name1, typename T1, typename... Modifiers1,
564 typename TableT2, fixed_string Name2, typename T2, typename... Modifiers2>
565auto operator-(const column<TableT1, Name1, T1, Modifiers1...>& left,
569
574
575 auto left_expr = query::to_expr(left);
576 auto right_expr = query::to_expr(right);
578 std::move(right_expr));
579}
580
582template <typename TableT, fixed_string Name, typename T, typename... Modifiers, typename ValueT>
583 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
584auto operator-(const column<TableT, Name, T, Modifiers...>& left, ValueT&& value) {
589 "Arithmetic operations require numeric values. Cannot subtract non-numeric values "
590 "from columns.");
591
592 auto left_expr = query::to_expr(left);
593 auto value_expr = query::val(std::forward<ValueT>(value));
595 std::move(value_expr));
596}
597
599template <typename ValueT, typename TableT, fixed_string Name, typename T, typename... Modifiers>
600 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
601auto operator-(ValueT&& value, const column<TableT, Name, T, Modifiers...>& right) {
606 "Arithmetic operations require numeric values.");
607
608 auto value_expr = query::val(std::forward<ValueT>(value));
609 auto right_expr = query::to_expr(right);
611 std::move(value_expr), "-", std::move(right_expr));
612}
613
615template <typename TableT1, fixed_string Name1, typename T1, typename... Modifiers1,
616 typename TableT2, fixed_string Name2, typename T2, typename... Modifiers2>
617auto operator*(const column<TableT1, Name1, T1, Modifiers1...>& left,
621
626
627 auto left_expr = query::to_expr(left);
628 auto right_expr = query::to_expr(right);
630 std::move(right_expr));
631}
632
634template <typename TableT, fixed_string Name, typename T, typename... Modifiers, typename ValueT>
635 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
636auto operator*(const column<TableT, Name, T, Modifiers...>& left, ValueT&& value) {
641 "Arithmetic operations require numeric values. Cannot multiply columns by "
642 "non-numeric values.");
643
644 auto left_expr = query::to_expr(left);
645 auto value_expr = query::val(std::forward<ValueT>(value));
647 std::move(value_expr));
648}
649
651template <typename ValueT, typename TableT, fixed_string Name, typename T, typename... Modifiers>
652 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
653auto operator*(ValueT&& value, const column<TableT, Name, T, Modifiers...>& right) {
654 return right * std::forward<ValueT>(value);
655}
656
658template <typename TableT1, fixed_string Name1, typename T1, typename... Modifiers1,
659 typename TableT2, fixed_string Name2, typename T2, typename... Modifiers2>
660auto operator/(const column<TableT1, Name1, T1, Modifiers1...>& left,
664
669
670 auto left_expr = query::to_expr(left);
671 auto right_expr = query::to_expr(right);
673 std::move(right_expr));
674}
675
677template <typename TableT, fixed_string Name, typename T, typename... Modifiers, typename ValueT>
678 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
679auto operator/(const column<TableT, Name, T, Modifiers...>& left, ValueT&& value) {
683 static_assert(
685 "Arithmetic operations require numeric values. Cannot divide columns by non-numeric values.");
686
687 auto left_expr = query::to_expr(left);
688 auto value_expr = query::val(std::forward<ValueT>(value));
690 std::move(value_expr));
691}
692
694template <typename ValueT, typename TableT, fixed_string Name, typename T, typename... Modifiers>
695 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
696auto operator/(ValueT&& value, const column<TableT, Name, T, Modifiers...>& right) {
701 "Arithmetic operations require numeric values.");
702
703 auto value_expr = query::val(std::forward<ValueT>(value));
704 auto right_expr = query::to_expr(right);
706 std::move(value_expr), "/", std::move(right_expr));
707}
708
709// Arithmetic operators for ArithmeticExpr to support chaining (in schema namespace for ADL)
710
712template <query::SqlExpr Left, query::SqlExpr Right, typename TableT, fixed_string Name, typename T,
713 typename... Modifiers>
714auto operator+(const query::ArithmeticExpr<Left, Right>& left_expr,
719
720 auto right_expr = query::to_expr(right);
722 left_expr, "+", std::move(right_expr));
723}
724
726template <typename TableT, fixed_string Name, typename T, typename... Modifiers,
727 query::SqlExpr Left, query::SqlExpr Right>
728auto operator+(const column<TableT, Name, T, Modifiers...>& left,
729 const query::ArithmeticExpr<Left, Right>& right_expr) {
733
734 auto left_expr = query::to_expr(left);
736 std::move(left_expr), "+", right_expr);
737}
738
740template <query::SqlExpr Left, query::SqlExpr Right, typename ValueT>
741 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
742auto operator+(const query::ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
744 "Arithmetic operations require numeric values.");
745
746 auto value_expr = query::val(std::forward<ValueT>(value));
748 left_expr, "+", std::move(value_expr));
749}
750
752template <typename ValueT, query::SqlExpr Left, query::SqlExpr Right>
753 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
754auto operator+(ValueT&& value, const query::ArithmeticExpr<Left, Right>& right_expr) {
755 return right_expr + std::forward<ValueT>(value);
756}
757
759template <query::SqlExpr Left, query::SqlExpr Right, typename TableT, fixed_string Name, typename T,
760 typename... Modifiers>
761auto operator-(const query::ArithmeticExpr<Left, Right>& left_expr,
766
767 auto right_expr = query::to_expr(right);
769 left_expr, "-", std::move(right_expr));
770}
771
773template <typename TableT, fixed_string Name, typename T, typename... Modifiers,
774 query::SqlExpr Left, query::SqlExpr Right>
775auto operator-(const column<TableT, Name, T, Modifiers...>& left,
776 const query::ArithmeticExpr<Left, Right>& right_expr) {
780
781 auto left_expr = query::to_expr(left);
783 std::move(left_expr), "-", right_expr);
784}
785
787template <query::SqlExpr Left, query::SqlExpr Right, typename ValueT>
788 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
789auto operator-(const query::ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
791 "Arithmetic operations require numeric values.");
792
793 auto value_expr = query::val(std::forward<ValueT>(value));
795 left_expr, "-", std::move(value_expr));
796}
797
799template <typename ValueT, query::SqlExpr Left, query::SqlExpr Right>
800 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
801auto operator-(ValueT&& value, const query::ArithmeticExpr<Left, Right>& right_expr) {
803 "Arithmetic operations require numeric values.");
804
805 auto value_expr = query::val(std::forward<ValueT>(value));
806 return query::ArithmeticExpr<decltype(value_expr), query::ArithmeticExpr<Left, Right>>(
807 std::move(value_expr), "-", right_expr);
808}
809
811template <query::SqlExpr Left, query::SqlExpr Right, typename TableT, fixed_string Name, typename T,
812 typename... Modifiers>
813auto operator*(const query::ArithmeticExpr<Left, Right>& left_expr,
818
819 auto right_expr = query::to_expr(right);
821 left_expr, "*", std::move(right_expr));
822}
823
825template <typename TableT, fixed_string Name, typename T, typename... Modifiers,
826 query::SqlExpr Left, query::SqlExpr Right>
827auto operator*(const column<TableT, Name, T, Modifiers...>& left,
828 const query::ArithmeticExpr<Left, Right>& right_expr) {
832
833 auto left_expr = query::to_expr(left);
835 std::move(left_expr), "*", right_expr);
836}
837
839template <query::SqlExpr Left, query::SqlExpr Right, typename ValueT>
840 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
841auto operator*(const query::ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
843 "Arithmetic operations require numeric values.");
844
845 auto value_expr = query::val(std::forward<ValueT>(value));
847 left_expr, "*", std::move(value_expr));
848}
849
851template <typename ValueT, query::SqlExpr Left, query::SqlExpr Right>
852 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
853auto operator*(ValueT&& value, const query::ArithmeticExpr<Left, Right>& right_expr) {
854 return right_expr * std::forward<ValueT>(value);
855}
856
858template <query::SqlExpr Left, query::SqlExpr Right, typename TableT, fixed_string Name, typename T,
859 typename... Modifiers>
860auto operator/(const query::ArithmeticExpr<Left, Right>& left_expr,
865
866 auto right_expr = query::to_expr(right);
868 left_expr, "/", std::move(right_expr));
869}
870
872template <typename TableT, fixed_string Name, typename T, typename... Modifiers,
873 query::SqlExpr Left, query::SqlExpr Right>
874auto operator/(const column<TableT, Name, T, Modifiers...>& left,
875 const query::ArithmeticExpr<Left, Right>& right_expr) {
879
880 auto left_expr = query::to_expr(left);
882 std::move(left_expr), "/", right_expr);
883}
884
886template <query::SqlExpr Left, query::SqlExpr Right, typename ValueT>
887 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
888auto operator/(const query::ArithmeticExpr<Left, Right>& left_expr, ValueT&& value) {
890 "Arithmetic operations require numeric values.");
891
892 auto value_expr = query::val(std::forward<ValueT>(value));
894 left_expr, "/", std::move(value_expr));
895}
896
898template <typename ValueT, query::SqlExpr Left, query::SqlExpr Right>
899 requires std::is_arithmetic_v<std::remove_cvref_t<ValueT>>
900auto operator/(ValueT&& value, const query::ArithmeticExpr<Left, Right>& right_expr) {
902 "Arithmetic operations require numeric values.");
903
904 auto value_expr = query::val(std::forward<ValueT>(value));
906 std::move(value_expr), "/", std::move(right_expr));
907}
908
909} // namespace relx::schema
Binary arithmetic expression.
ArithmeticExpr(Left left, std::string op, Right right)
std::string table_name() const override
std::string to_sql() const override
std::vector< std::string > bind_params() const override
std::string column_name() const override
Base class for column expressions.
Represents a column in a database table.
Definition column.hpp:217
Concept for SQL expression components.
Definition core.hpp:29
Concept for numeric types suitable for arithmetic operations.
typename extract_arithmetic_type< T >::type extract_arithmetic_type_t
constexpr std::string_view arithmetic_error_message
Error message for invalid arithmetic operations.
typename remove_optional< T >::type remove_optional_t
auto operator-(const schema::column< TableT1, Name1, T1, Modifiers1... > &left, const schema::column< TableT2, Name2, T2, Modifiers2... > &right)
Subtraction operator for columns.
auto to_expr(const C &col, std::string_view table_name="")
Helper to wrap a schema column in a SQL expression.
auto operator/(const schema::column< TableT1, Name1, T1, Modifiers1... > &left, const schema::column< TableT2, Name2, T2, Modifiers2... > &right)
Division operator for columns.
auto value(T val)
Create a value expression.
Definition value.hpp:120
auto operator+(const schema::column< TableT1, Name1, T1, Modifiers1... > &left, const schema::column< TableT2, Name2, T2, Modifiers2... > &right)
Addition operator for columns with type checking.
auto val(const char *str)
Helper to create a value expression from a string literal.
Definition value.hpp:127
auto operator*(const schema::column< TableT1, Name1, T1, Modifiers1... > &left, const schema::column< TableT2, Name2, T2, Modifiers2... > &right)
Multiplication operator for columns.
STL namespace.
Helper to extract column type for arithmetic checking.
Helper to extract base type from optional.
Compile-time string type that can be used as template non-type parameter in C++20.