Question

I have this JayData query (it can be checked at JSLQ playground):

northwind.Products
  .filter( function( product ) {
    return  product.ProductName.toLowerCase() in ['tofu'];
  } )
  .toArray( function( products ) {
    console.dir( products );
  } );

For some unknown reasons this query produces incorrect filter expression: http://services.odata.org/Northwind/Northwind.svc/Products?$filter=(tolowerProductName%20eq%20%27tofu%27)&$callback=parent.handleJSONP_21&$format=json

I highlighted incorrect parameter with bold above.

So you can see that we have tolowerProductName, but it should be tolower(ProductName), so the right filter query should looks like this: http://services.odata.org/Northwind/Northwind.svc/Products?$filter=%28tolower%28ProductName%29%20eq%20%27tofu%27%29&$callback=parent.handleJSONP_21&$format=json

Is anybody know a workaround?

Update: Issue occurs only when I use toLowerCase with "in [array]", so for example this query is working just fine:

northwind.Products
  .filter( function( product ) {
    return  product.ProductName in ['Tofu'];
  } )
  .toArray( function( products ) {
    console.dir( products );
  } );

This query with toLowerCase is working just fine too:

northwind.Products
  .filter( function( product ) {
    return  product.ProductName.toLowerCase() == 'Tofu';
  } )
  .toArray( function( products ) {
    console.dir( products );
  } );

Thank you!

Was it helpful?

Solution 2

I found that incorrect filter expression produces this line of code (for query with 'in' operator):

context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');

Line 1542 in oDataProvider.js

I replaced it with this code:

context.data = temp + context.data;

And now everything is working as expected. Maybe I introduced other issues with this fix, but at least it works as expected for my queries.

So the VisitSimpleBinaryExpression function looks like this now:

VisitSimpleBinaryExpression: function (expression, context) {
        context.data += "(";
        //TODO refactor!!!
        if (expression.nodeType == "in") {
            Guard.requireType("expression.right", expression.type, $data.Expressions.ConstantExpression);
            var paramValue = expression.right.value;
            if (!paramValue instanceof Array) { Guard.raise(new Exception("Right to the 'in' operator must be an array value")); }
            var result = null;
            var orResolution = { mapTo: "or", dataType: "boolean", name: "or" };
            var eqResolution = { mapTo: "eq", dataType: "boolean", name: "equal" };

            paramValue.forEach(function (item) {
                var idValue = item;
                var idCheck = Container.createSimpleBinaryExpression(expression.left, idValue,
                    $data.Expressions.ExpressionType.Equal, "==", "boolean", eqResolution);
                if (result) {
                    result = Container.createSimpleBinaryExpression(result, idCheck,
                    $data.Expressions.ExpressionType.Or, "||", "boolean", orResolution);
                } else {
                    result = idCheck;
                };
            });
            var temp = context.data;
            context.data = '';
            this.Visit(result, context);
            //context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');
            context.data = temp + context.data;
        } else {
            this.Visit(expression.left, context);
            context.data += " ";
            context.data += expression.resolution.mapTo;
            context.data += " ";
            this.Visit(expression.right, context);
        };
        context.data += ")";

    },

OTHER TIPS

Have you tried setting that expression to a variable and then checking for that in ['tofu']?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top