support for null queries
This commit is contained in:
parent
805fdc63a7
commit
6a05db6aed
|
@ -56,6 +56,7 @@ struct number : seq< minus, sor< float_num, hex_num, int_num > > {};
|
|||
|
||||
struct true_value : pegtl_istring_t("true") {};
|
||||
struct false_value : pegtl_istring_t("false") {};
|
||||
struct null_value : pegtl_istring_t("null") {};
|
||||
|
||||
// key paths
|
||||
struct key_path : list< seq< sor< alpha, one< '_' > >, star< sor< alnum, one< '_', '-' > > > >, one< '.' > > {};
|
||||
|
@ -65,7 +66,7 @@ struct argument_index : plus< digit > {};
|
|||
struct argument : seq< one< '$' >, must< argument_index > > {};
|
||||
|
||||
// expressions and operators
|
||||
struct expr : sor< dq_string, sq_string, number, argument, true_value, false_value, key_path > {};
|
||||
struct expr : sor< dq_string, sq_string, number, argument, true_value, false_value, null_value, key_path > {};
|
||||
struct case_insensitive : pegtl_istring_t("[c]"){};
|
||||
|
||||
struct eq : seq< sor< two< '=' >, one< '=' > >, opt< case_insensitive > >{};
|
||||
|
@ -236,6 +237,7 @@ EXPRESSION_ACTION(key_path, Expression::Type::KeyPath)
|
|||
EXPRESSION_ACTION(number, Expression::Type::Number)
|
||||
EXPRESSION_ACTION(true_value, Expression::Type::True)
|
||||
EXPRESSION_ACTION(false_value, Expression::Type::False)
|
||||
EXPRESSION_ACTION(null_value, Expression::Type::Null)
|
||||
EXPRESSION_ACTION(argument_index, Expression::Type::Argument)
|
||||
|
||||
template<> struct action< true_pred >
|
||||
|
|
|
@ -28,7 +28,7 @@ class Schema;
|
|||
namespace parser {
|
||||
struct Expression
|
||||
{
|
||||
enum class Type { None, Number, String, KeyPath, Argument, True, False } type;
|
||||
enum class Type { None, Number, String, KeyPath, Argument, True, False, Null } type;
|
||||
std::string s;
|
||||
Expression(Type t = Type::None, std::string s = "") : type(t), s(s) {}
|
||||
};
|
||||
|
|
|
@ -265,22 +265,6 @@ void add_link_constraint_to_query(realm::Query &query,
|
|||
}
|
||||
}
|
||||
|
||||
void add_link_constraint_to_query(realm::Query &query,
|
||||
Predicate::Operator op,
|
||||
PropertyExpression &prop_expr,
|
||||
realm::null) {
|
||||
precondition(prop_expr.indexes.empty(), "KeyPath queries not supported for object comparisons.");
|
||||
switch (op) {
|
||||
case Predicate::Operator::NotEqual:
|
||||
query.Not();
|
||||
case Predicate::Operator::Equal:
|
||||
query.and_query(query.get_table()->column<Link>(prop_expr.prop->table_column).is_null());
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Only 'equal' and 'not equal' operators supported for object comparison.");
|
||||
}
|
||||
}
|
||||
|
||||
auto link_argument(const PropertyExpression &propExpr, const parser::Expression &argExpr, Arguments &args)
|
||||
{
|
||||
return args.object_index_for_argument(stot<int>(argExpr.s));
|
||||
|
@ -439,6 +423,50 @@ void do_add_comparison_to_query(Query &query, const Schema &schema, const Object
|
|||
}
|
||||
}
|
||||
|
||||
void do_add_null_comparison_to_query(Query &query, const Schema &schema, const ObjectSchema &object_schema, Predicate::Comparison cmp, const PropertyExpression &expr, Arguments &args)
|
||||
{
|
||||
auto type = expr.prop->type;
|
||||
switch (type) {
|
||||
case PropertyTypeObject:
|
||||
precondition(expr.indexes.empty(), "KeyPath queries not supported for object comparisons.");
|
||||
switch (cmp.op) {
|
||||
case Predicate::Operator::NotEqual:
|
||||
query.Not();
|
||||
case Predicate::Operator::Equal:
|
||||
query.and_query(query.get_table()->column<Link>(expr.prop->table_column).is_null());
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Only 'equal' and 'not equal' operators supported for object comparison.");
|
||||
}
|
||||
break;
|
||||
case PropertyTypeArray:
|
||||
throw std::runtime_error((std::string)"Comparing Lists to 'null' is not supported");
|
||||
break;
|
||||
default: {
|
||||
switch (cmp.op) {
|
||||
case Predicate::Operator::NotEqual:
|
||||
query.not_equal(expr.prop->table_column, realm::null());
|
||||
break;
|
||||
case Predicate::Operator::Equal:
|
||||
query.equal(expr.prop->table_column, realm::null());
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Only 'equal' and 'not equal' operators supported for object comparison.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool expression_is_null(const parser::Expression &expr, Arguments &args) {
|
||||
if (expr.type == parser::Expression::Type::Null) {
|
||||
return true;
|
||||
}
|
||||
else if (expr.type == parser::Expression::Type::Argument) {
|
||||
return args.is_argument_null(stot<int>(expr.s));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void add_comparison_to_query(Query &query, const Predicate &pred, Arguments &args, const Schema &schema, const std::string &type)
|
||||
{
|
||||
const Predicate::Comparison &cmpr = pred.cmpr;
|
||||
|
@ -446,11 +474,21 @@ void add_comparison_to_query(Query &query, const Predicate &pred, Arguments &arg
|
|||
auto object_schema = schema.find(type);
|
||||
if (t0 == parser::Expression::Type::KeyPath && t1 != parser::Expression::Type::KeyPath) {
|
||||
PropertyExpression expr(query, schema, object_schema, cmpr.expr[0].s);
|
||||
do_add_comparison_to_query(query, schema, *object_schema, cmpr, expr, expr, cmpr.expr[1], args);
|
||||
if (expression_is_null(cmpr.expr[1], args)) {
|
||||
do_add_null_comparison_to_query(query, schema, *object_schema, cmpr, expr, args);
|
||||
}
|
||||
else {
|
||||
do_add_comparison_to_query(query, schema, *object_schema, cmpr, expr, expr, cmpr.expr[1], args);
|
||||
}
|
||||
}
|
||||
else if (t0 != parser::Expression::Type::KeyPath && t1 == parser::Expression::Type::KeyPath) {
|
||||
PropertyExpression expr(query, schema, object_schema, cmpr.expr[1].s);
|
||||
do_add_comparison_to_query(query, schema, *object_schema, cmpr, expr, cmpr.expr[0], expr, args);
|
||||
if (expression_is_null(cmpr.expr[0], args)) {
|
||||
do_add_null_comparison_to_query(query, schema, *object_schema, cmpr, expr, args);
|
||||
}
|
||||
else {
|
||||
do_add_comparison_to_query(query, schema, *object_schema, cmpr, expr, cmpr.expr[0], expr, args);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Predicate expressions must compare a keypath and another keypath or a constant value");
|
||||
|
|
Loading…
Reference in New Issue