#include "luabindings.hpp" namespace sol { template <> struct is_automagical<Queries::Field> : std::false_type {}; template <> struct is_automagical<Queries::Filter> : std::false_type {}; template <> struct is_automagical<Queries::Query> : std::false_type {}; } namespace Queries { template <Condition::Type type> struct CondBuilder { Filter operator()(const Field& field, const sol::object& o) { FieldValue value; if (field.type() == typeid(bool) && o.is<bool>()) value = o.as<bool>(); else if (field.type() == typeid(int32_t) && o.is<int32_t>()) value = o.as<int32_t>(); else if (field.type() == typeid(int64_t) && o.is<int64_t>()) value = o.as<int64_t>(); else if (field.type() == typeid(float) && o.is<float>()) value = o.as<float>(); else if (field.type() == typeid(double) && o.is<double>()) value = o.as<double>(); else if (field.type() == typeid(std::string) && o.is<std::string>()) value = o.as<std::string>(); else throw std::logic_error("Invalid value for field " + field.toString()); Filter filter; filter.add({&field, type, value}); return filter; } }; void registerQueryBindings(sol::state& lua) { sol::usertype<Field> field = lua.new_usertype<Field>("QueryField"); sol::usertype<Filter> filter = lua.new_usertype<Filter>("QueryFilter"); sol::usertype<Query> query = lua.new_usertype<Query>("Query"); field[sol::meta_function::to_string] = [](const Field& f) { return f.toString(); }; field["eq"] = CondBuilder<Condition::EQUAL>(); field["neq"] = CondBuilder<Condition::NOT_EQUAL>(); field["lt"] = CondBuilder<Condition::LESSER>(); field["lte"] = CondBuilder<Condition::LESSER_OR_EQUAL>(); field["gt"] = CondBuilder<Condition::GREATER>(); field["gte"] = CondBuilder<Condition::GREATER_OR_EQUAL>(); field["like"] = CondBuilder<Condition::LIKE>(); filter[sol::meta_function::to_string] = [](const Filter& filter) { return filter.toString(); }; filter[sol::meta_function::multiplication] = [](const Filter& a, const Filter& b) { Filter res = a; res.add(b, Operation::AND); return res; }; filter[sol::meta_function::addition] = [](const Filter& a, const Filter& b) { Filter res = a; res.add(b, Operation::OR); return res; }; filter[sol::meta_function::unary_minus] = [](const Filter& a) { Filter res = a; if (!a.mConditions.empty()) res.mOperations.push_back({Operation::NOT, 0}); return res; }; query[sol::meta_function::to_string] = [](const Query& q) { return q.toString(); }; query["where"] = [](const Query& q, const Filter& filter) { Query res = q; res.mFilter.add(filter, Operation::AND); return res; }; query["orderBy"] = [](const Query& q, const Field& field) { Query res = q; res.mOrderBy.push_back({&field, false}); return res; }; query["orderByDesc"] = [](const Query& q, const Field& field) { Query res = q; res.mOrderBy.push_back({&field, true}); return res; }; query["groupBy"] = [](const Query& q, const Field& field) { Query res = q; res.mGroupBy.push_back(&field); return res; }; query["offset"] = [](const Query& q, int64_t offset) { Query res = q; res.mOffset = offset; return res; }; query["limit"] = [](const Query& q, int64_t limit) { Query res = q; res.mLimit = limit; return res; }; } }