react-querybuilder/react-querybuilder

parseCEL does not work well as parseJsonLogic

i-am-choco opened this issue · 1 comments

React Query Builder version

v6.5.5

Platform

No response

Description

Hi, I am new to using react-querybuilder.
Due to project requirements, there arises a scenario where field configurations need to be dynamically created.
And I found that parseCEL does not work well as parseJsonLogic.

Reproduction

The query would be like this

const query =  {
    "id": "f2cf2612-288a-4ecc-be8f-07f7d755bb7b",
    "combinator": "and",
    "rules": [
        {
            "id": "7ce77daf-4c35-4c14-890b-bbf8cb5b1986",
            "field": "be321f6d-8eba-4dc4-b783-2cda07b424f4",
            "operator": "contains",
            "valueSource": "value",
            "value": "a"
        }
    ]
}

And I would use formatQuery to get which fomart I want.
However, I found the results between parseCEL(formatQuery(query, "cel")) and parseJsonLogic(formatQuery(query, "jsonlogic")) are different.

const resultCEL = parseCEL(formatQuery(query, "cel"));
// actual
//   {
//     "rules": [],
//     "combinator": "and"
// }

// expected
//{
//     "combinator": "and",
//     "rules": [
//         {
//             "field": "be321f6d-8eba-4dc4-b783-2cda07b424f4",
//             "operator": "contains",
//             "value": "a"
//         }
//     ]
// }

const resultsJsonLogic = parseJsonLogic(formatQuery(query, "jsonlogic"));

// actual
//{
//     "combinator": "and",
//     "rules": [
//         {
//             "field": "be321f6d-8eba-4dc4-b783-2cda07b424f4",
//             "operator": "contains",
//             "value": "a"
//         }
//     ]
// }


Expected behavior

parseCEL will work well as parseJsonLogic

Additional information

After debugging the problem, I found that replacing all '-' within the 'field' resolved the problem.

This isn't an issue with parseCEL so much as a limitation of CEL syntax. According to the CEL grammar spec, there is no way to bracket identifiers to allow characters outside the regex [_a-zA-Z][_a-zA-Z0-9]*.

For the SQL-based exports, we have the quoteFieldNamesWith option which allows you to bracket field names like `fieldName` = 'value' or [fieldName] = 'value'. The option has no effect on the CEL export because it would produce an invalid expression, which is also why parseCEL won't recognize it as valid syntax.

I would suggest using transformQuery to do something like this:

// Export
formatQuery(
  transformQuery(
    { combinator: 'and', rules: [{ field: 'x-y-z', operator: '=', value: 'v' }] },
    { ruleProcessor: r => ({ ...r, field: r.field.replaceAll('-', '_') }) }
  ),
  'cel'
);
// -> `x_y_z == "v"`

// Import
transformQuery(parseCEL(`x_y_z == "v"`), {
  ruleProcessor: r => ({ ...r, field: r.field.replaceAll('_', '-') }),
});
// -> {"combinator":"and","rules":[{"field":"x-y-z","operator":"=","value":"v"}]}