@@ -42,6 +42,7 @@ struct REFLECTION_EXPORT SqlValue {
4242 bool bool_value;
4343 double real_value;
4444 std::string text_value;
45+ bool is_null;
4546};
4647
4748// / The base class of all WHERE predicates used in SQLite queries
@@ -103,13 +104,20 @@ class REFLECTION_EXPORT QueryPredicate : public QueryPredicateBase {
103104 : QueryPredicate(fn, value, symbol,
104105 [&](void * v, SqliteStorageClass storage_class) { return GetSqlValue (v, storage_class); }) {}
105106
107+ template <typename T, typename R>
108+ QueryPredicate (fcpp::optional_t <R> T::* fn, R value, const std::string& symbol)
109+ : QueryPredicate(fn, fcpp::optional_t <R>(value), symbol, [&](void * v, SqliteStorageClass storage_class) {
110+ return GetOptionalSqlValue (v, storage_class);
111+ }) {}
112+
106113 QueryPredicate (const std::string& symbol, const std::string& member_name, const SqlValue& value)
107114 : symbol_(symbol), member_name_(member_name), value_(value) {}
108115
109116 // / Returns the value used for the current query, against which the struct member
110117 // / (defined from the pointer-to-member function) will be compared. The value needs
111118 // / to be type-erased, so that the header file is not bloated with unnecessary implementation details
112119 virtual SqlValue GetSqlValue (void * v, SqliteStorageClass storage_class) const ;
120+ virtual SqlValue GetOptionalSqlValue (void * v, SqliteStorageClass storage_class) const ;
113121
114122 // / The symbol used for the comparison, for example "=" for equality
115123 std::string symbol_;
@@ -122,6 +130,47 @@ class REFLECTION_EXPORT QueryPredicate : public QueryPredicateBase {
122130 SqlValue value_;
123131};
124132
133+ // / A wrapper for an empty predicate, used to fetch all elements of an SQLite table
134+ class REFLECTION_EXPORT NullPredicate : public QueryPredicateBase {
135+ public:
136+ template <typename T, typename R>
137+ NullPredicate (R T::* fn, const std::string& symbol) : symbol_(symbol) {
138+ auto record = GetRecordFromTypeId (typeid (T).name ());
139+ auto offset = OffsetFromStart (fn);
140+ for (auto i = 0 ; i < record.member_metadata .size (); ++i) {
141+ if (record.member_metadata [i].offset == offset) {
142+ member_name_ = record.member_metadata [i].name ;
143+ return ;
144+ }
145+ }
146+ throw std::runtime_error (" No registered member of '" + record.name +
147+ " ' matches the given pointer-to-member (type id: " + typeid (T).name () + " )" );
148+ }
149+
150+ std::string Evaluate () const override ;
151+ std::vector<SqlValue> Bindings () const override ;
152+ QueryPredicateBase* Clone () const override ;
153+
154+ protected:
155+ NullPredicate (const std::string& symbol, const std::string& member_name)
156+ : symbol_(symbol), member_name_(member_name) {}
157+
158+ std::string symbol_;
159+ std::string member_name_;
160+ };
161+
162+ class REFLECTION_EXPORT IsNull final : public NullPredicate {
163+ public:
164+ template <typename T, typename R>
165+ explicit IsNull (R T::* fn) : NullPredicate(fn, " IS NULL" ) {}
166+ };
167+
168+ class REFLECTION_EXPORT IsNotNull final : public NullPredicate {
169+ public:
170+ template <typename T, typename R>
171+ explicit IsNotNull (R T::* fn) : NullPredicate(fn, " IS NOT NULL" ) {}
172+ };
173+
125174// / A wrapper for an empty predicate, used to fetch all elements of an SQLite table
126175class REFLECTION_EXPORT EmptyPredicate final : public QueryPredicateBase {
127176public:
@@ -137,6 +186,9 @@ class REFLECTION_EXPORT Equal final : public QueryPredicate {
137186 template <typename T, typename R>
138187 explicit Equal (R T::* fn, R value) : QueryPredicate(fn, value, " =" ) {}
139188
189+ template <typename T, typename R>
190+ explicit Equal (fcpp::optional_t <R> T::* fn, R value) : QueryPredicate(fn, value, " =" ) {}
191+
140192 template <typename T>
141193 explicit Equal (int64_t T::* fn, int value) : Equal(fn, (int64_t )value) {}
142194
@@ -151,6 +203,9 @@ class REFLECTION_EXPORT Unequal final : public QueryPredicate {
151203 template <typename T, typename R>
152204 explicit Unequal (R T::* fn, R value) : QueryPredicate(fn, value, " !=" ) {}
153205
206+ template <typename T, typename R>
207+ explicit Unequal (fcpp::optional_t <R> T::* fn, R value) : QueryPredicate(fn, value, " !=" ) {}
208+
154209 template <typename T>
155210 explicit Unequal (int64_t T::* fn, int value) : Unequal(fn, (int64_t )value) {}
156211
@@ -167,6 +222,12 @@ class REFLECTION_EXPORT Like final : public QueryPredicate {
167222 : QueryPredicate(fn, value, " LIKE" ,
168223 [&](void * v, SqliteStorageClass storage_class) { return GetSqlValue (v, storage_class); }) {}
169224
225+ template <typename T, typename R>
226+ explicit Like (fcpp::optional_t <R> T::* fn, R value)
227+ : QueryPredicate(fn, fcpp::optional_t <R>(value), "LIKE", [&](void * v, SqliteStorageClass storage_class) {
228+ return GetOptionalSqlValue (v, storage_class);
229+ }) {}
230+
170231 template <typename T>
171232 explicit Like (int64_t T::* fn, int value) : Like(fn, (int64_t )value) {}
172233
@@ -189,6 +250,12 @@ class REFLECTION_EXPORT GreaterThan final : public QueryPredicate {
189250
190251 template <typename T>
191252 explicit GreaterThan (double T::* fn, double value) : QueryPredicate(fn, value, " >" ) {}
253+
254+ template <typename T>
255+ explicit GreaterThan (fcpp::optional_t <int64_t > T::* fn, int64_t value) : QueryPredicate(fn, value, " >" ) {}
256+
257+ template <typename T>
258+ explicit GreaterThan (fcpp::optional_t <double > T::* fn, double value) : QueryPredicate(fn, value, " >" ) {}
192259};
193260
194261// / A wrapper for a comparison predicate, for which the value of the
@@ -203,6 +270,12 @@ class REFLECTION_EXPORT GreaterThanOrEqual final : public QueryPredicate {
203270
204271 template <typename T>
205272 explicit GreaterThanOrEqual (double T::* fn, double value) : QueryPredicate(fn, value, " >=" ) {}
273+
274+ template <typename T>
275+ explicit GreaterThanOrEqual (fcpp::optional_t <int64_t > T::* fn, int64_t value) : QueryPredicate(fn, value, " >=" ) {}
276+
277+ template <typename T>
278+ explicit GreaterThanOrEqual (fcpp::optional_t <double > T::* fn, double value) : QueryPredicate(fn, value, " >=" ) {}
206279};
207280
208281// / A wrapper for a comparison predicate, for which the value of the
@@ -217,6 +290,12 @@ class REFLECTION_EXPORT SmallerThan final : public QueryPredicate {
217290
218291 template <typename T>
219292 explicit SmallerThan (double T::* fn, double value) : QueryPredicate(fn, value, " <" ) {}
293+
294+ template <typename T>
295+ explicit SmallerThan (fcpp::optional_t <int64_t > T::* fn, int64_t value) : QueryPredicate(fn, value, " <" ) {}
296+
297+ template <typename T>
298+ explicit SmallerThan (fcpp::optional_t <double > T::* fn, double value) : QueryPredicate(fn, value, " <" ) {}
220299};
221300
222301// / A wrapper for a comparison predicate, for which the value of the
@@ -231,6 +310,12 @@ class REFLECTION_EXPORT SmallerThanOrEqual final : public QueryPredicate {
231310
232311 template <typename T>
233312 explicit SmallerThanOrEqual (double T::* fn, double value) : QueryPredicate(fn, value, " <=" ) {}
313+
314+ template <typename T>
315+ explicit SmallerThanOrEqual (fcpp::optional_t <int64_t > T::* fn, int64_t value) : QueryPredicate(fn, value, " <=" ) {}
316+
317+ template <typename T>
318+ explicit SmallerThanOrEqual (fcpp::optional_t <double > T::* fn, double value) : QueryPredicate(fn, value, " <=" ) {}
234319};
235320
236321// / A wrapper of a compound predicate, which combines two other predicates,
0 commit comments