|
@@ -0,0 +1,42 @@
|
|
|
|
|
+#include "filters.hpp"
|
|
|
|
|
+#include "errors.hpp"
|
|
|
|
|
+#include <unordered_map>
|
|
|
|
|
+
|
|
|
|
|
+namespace svapi {
|
|
|
|
|
+
|
|
|
|
|
+using Op = smartbotic::database::Client::FilterOp;
|
|
|
|
|
+
|
|
|
|
|
+Op opFromSlug(const std::string& slug) {
|
|
|
|
|
+ static const std::unordered_map<std::string, Op> m = {
|
|
|
|
|
+ {"eq", Op::EQ}, {"ne", Op::NE}, {"gt", Op::GT}, {"gte", Op::GTE},
|
|
|
|
|
+ {"lt", Op::LT}, {"lte", Op::LTE}, {"in", Op::IN}, {"contains", Op::CONTAINS},
|
|
|
|
|
+ {"exists", Op::EXISTS}, {"regex", Op::REGEX}, {"search", Op::SEARCH},
|
|
|
|
|
+ };
|
|
|
|
|
+ auto it = m.find(slug);
|
|
|
|
|
+ if (it == m.end())
|
|
|
|
|
+ throw ApiError(ErrCode::BadRequest, "bad_filter", "unknown filter operator: " + slug);
|
|
|
|
|
+ return it->second;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+smartbotic::database::Client::Filter parseFilter(const std::string& spec) {
|
|
|
|
|
+ auto p1 = spec.find(':');
|
|
|
|
|
+ if (p1 == std::string::npos)
|
|
|
|
|
+ throw ApiError(ErrCode::BadRequest, "bad_filter", "filter must be field:op:value: " + spec);
|
|
|
|
|
+ auto p2 = spec.find(':', p1 + 1);
|
|
|
|
|
+ if (p2 == std::string::npos)
|
|
|
|
|
+ throw ApiError(ErrCode::BadRequest, "bad_filter", "filter must be field:op:value: " + spec);
|
|
|
|
|
+
|
|
|
|
|
+ std::string field = spec.substr(0, p1);
|
|
|
|
|
+ std::string opSlug = spec.substr(p1 + 1, p2 - p1 - 1);
|
|
|
|
|
+ std::string rawValue = spec.substr(p2 + 1);
|
|
|
|
|
+
|
|
|
|
|
+ nlohmann::json value;
|
|
|
|
|
+ try {
|
|
|
|
|
+ value = nlohmann::json::parse(rawValue);
|
|
|
|
|
+ } catch (...) {
|
|
|
|
|
+ value = rawValue; // fall back to string
|
|
|
|
|
+ }
|
|
|
|
|
+ return {field, opFromSlug(opSlug), value};
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+} // namespace svapi
|