PredicateExpression constructor taking predicate is not the same as adding

Posts   
 
    
hotchill avatar
hotchill
User
Posts: 180
Joined: 22-Jan-2007
# Posted on: 10-May-2017 14:46:28   

Hi.

I was surprised to find that this:

var filter = new RelationPredicateBucket(predicateA | predicateB | predicateC);
filter.PredicateExpression.Add(predicateD);

is not the same as this:

var filter = new RelationPredicateBucket();
filter.PredicateExpression.Add(predicateA | predicateB | predicateC);
filter.PredicateExpression.Add(predicateD);

Is this by design?

I am on v4.2 Final using adapter.

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 10-May-2017 17:29:49   

Yes, by design.

In the first example, you are adding predicates to the Bucket in the constructor, then you are adding another one later.

var filter = new RelationPredicateBucket(predicateA | predicateB | predicateC);
filter.PredicateExpression.Add(predicateD);

So all of them are added without brackets grouping some of them. In this case the And precede the OR in the databse, and the logic is that pA | pB | (pC & pD)

Now if you want to have (A | B | C) & (D), then you will group each into a predicate expression.

hotchill avatar
hotchill
User
Posts: 180
Joined: 22-Jan-2007
# Posted on: 10-May-2017 17:33:51   

Thanks Walaa, good to know.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 10-May-2017 20:18:23   

Actually, they should be the same. What difference do you see?

As the constructor calls Add(predicate) with the ctor argument: http://referencesource42.llblgen.com/#SD.LLBLGen.Pro.ORMSupportClasses/QueryApiElements/RelationPredicateBucket.cs,108

the 3 or-ed predicates should evaluate first to a PredicateExpression, then that single expression is added to the bucket's predicate expression as if you called Add() later (like in your second example).

Looking at the code I don't see what the differences are, could you elaborate on that a bit?

Frans Bouma | Lead developer LLBLGen Pro
hotchill avatar
hotchill
User
Posts: 180
Joined: 22-Jan-2007
# Posted on: 10-May-2017 20:27:55   

I see difference as pointed out by Walaa.

Former: (A | B) | C & D Latter: (A | B | C) & D

Anyone else needing to find usages for code review, turn on reg.ex. in VS search and use this: new RelationPredicateBucket(.*|

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 11-May-2017 12:56:29   

Thanks, we'll look into it, as they should be the same simple_smile (namely the latter)

Frans Bouma | Lead developer LLBLGen Pro
hotchill avatar
hotchill
User
Posts: 180
Joined: 22-Jan-2007
# Posted on: 11-May-2017 13:35:49   

Great, you're welcome simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 11-May-2017 15:03:55   

Ok, there's a bit of confusion what should happen and this is unfortunate. The idea of the constructor is: these are the elements to build the bucket with. This means that the predicate expression passed in is actually the predicate expression of the bucket. It's not wrapped again.

So calling 'Add' after that, will add to that predicate expression object.

In the case of the 2nd example, you start with an empty predicate expression, and you add the predicate expression with the 3 or-ed predicates to that. After that calling add again, adds to the original one, the empty predicate expression you started with.

It's a line in the reference manual documentation on the constructor: Filter to use. Will be set as the initial PredicateExpression contents

this is a bit misleading, as it is up for interpretation and can cause confusion like we've seen in this thread.

My initial reaction was as well: they should be the same, but the API is a little bit different. We can't change the API however, so no fix for this to make them align can be issued. This might sound a little odd, but wrapping it in a predicate expression causes a different sql string which might cause tests to fail for no reason. It also might cause code to fail which uses this feature and assumes the predicateexpression is the same object (as the api intended). We'll update the comment on the constructor to make it more clear that a passed in predicateexpression will be used as the predicateexpression of the bucket.

Hopefully this clears things up a bit simple_smile

Frans Bouma | Lead developer LLBLGen Pro
hotchill avatar
hotchill
User
Posts: 180
Joined: 22-Jan-2007
# Posted on: 11-May-2017 15:09:35   

Sure simple_smile Getting rid of this oddity now would likely cause much problems. You guys made the right decision documenting it instead.