|
From: Andrey T. (JIRA) <nh...@gm...> - 2011-01-13 18:34:27
|
NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
-------------------------------------------------------------------------------
Key: NH-2500
URL: http://216.121.112.228/browse/NH-2500
Project: NHibernate
Issue Type: Bug
Components: Linq Provider
Affects Versions: 3.0.0.GA
Reporter: Andrey Titov
Priority: Critical
Attachments: NHTest3.zip
NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
//in first session
this.number = 545;
var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
// all works perfect: all CatInfos contains 545
//later in another session
this.number = 842;
var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
// magic happens: all CatInfos contains 545 again
I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Nicola T. (JIRA) <nh...@gm...> - 2011-01-23 18:07:16
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Nicola Tuveri updated NH-2500:
------------------------------
Attachment: NH-2500.patch
Attached a patch that fix the issue. The patch is generated targeting revision 5365.
Constants were compiled into the lambda used to shape the result.
In the patch constants are converted into parameters and refreshed each execution of a cached query.
The issue is the same demonstrated in the test attached to NH-2397 by Joao Braganca.
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Priority: Critical
> Attachments: NH-2500.patch, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Patrick E. (JIRA) <nh...@gm...> - 2011-01-23 20:36:15
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Patrick Earl reassigned NH-2500:
--------------------------------
Assignee: Patrick Earl
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Assignee: Patrick Earl
> Priority: Critical
> Attachments: NH-2500.patch, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Patrick E. (JIRA) <nh...@gm...> - 2011-01-24 05:23:29
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=20505#action_20505 ]
Patrick Earl commented on NH-2500:
----------------------------------
Hi Nicola. I looked through your patch and have a couple questions.
1. Have you considered what might happen with subqueries? I'm still learning about the code myself, but I saw some indication that subqueries also use the result transformer, and I'm not sure if the current code covers those cases. I came up with this thought after looking to see if the ResultTransformer constructor could be called with the list of constants, instead of setting it directly as a property.
2. It seems like the ExpressionKeyVisitor would also need to be adjusted. Did you or could you look into this as well?
3. As a random thought, it would be good if NHibernate didn't maintain references to the external objects in any query/expression cache so things can be garbage collected properly.
Thanks so much for the work you put into the patch!
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Assignee: Patrick Earl
> Priority: Critical
> Attachments: NH-2500.patch, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Nicola T. (JIRA) <nh...@gm...> - 2011-01-24 10:37:31
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=20506#action_20506 ]
Nicola Tuveri commented on NH-2500:
-----------------------------------
Hi Patrick.
1. Good point. I'll write some tests to cover more complex queries, starting with subqueries.
Using a property to set the list of constants like I did it's dirty, I know.
On the other hand the constructor of ResultTransformer is called before the query is cached, so constants would be cached as well.
I'll try to find a better way to accomplish this, checking other classes as well.
Could ExpressionQueryImpl and HQLExpressionQueryPlan along with thier related interfaces be good candidates?
I'll check how NHibernate handles constants in regular (non Linq) queries too.
2. Yes I did, but I don't understand the exact point you are referring to.
I would be happy to adjust ExpressionKeyVisitor following your suggestion.
3. Right. Are you referring to the Constants property of the result transformer?
Thanks for reviewing the patch!
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Assignee: Patrick Earl
> Priority: Critical
> Attachments: NH-2500.patch, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Andrey T. (JIRA) <nh...@gm...> - 2011-01-24 20:48:40
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=20509#action_20509 ]
Andrey Titov commented on NH-2500:
----------------------------------
Please be aware in NHibernate-3.0.0.GA plans are cached by string key not containing types. So second queries in following pairs will throw InvalidCastException:
var cats = session.Query<Cat>().Select(cat => new CatInfo<string> { Name = cat.Name, SomeObject = "8989", }).ToList();
var cats = session.Query<Cat>().Select(cat => new CatInfo<int> { Name = cat.Name, SomeObject = 5675, }).ToList();
const string number = "3876";
var cats = session.Query<Cat>().Select(cat => number).ToList();
const int number = 4378;
var cats = session.Query<Cat>().Select(cat => number).ToList();
Two similar bugs were fixed: NH-2433 and NH-2459. I havn't check does this fix covers this scenario, but please take care to types when substityting constant values.
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Assignee: Patrick Earl
> Priority: Critical
> Attachments: NH-2500.patch, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Cameron H. (JIRA) <nh...@gm...> - 2011-05-10 09:57:51
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Cameron Harris updated NH-2500:
-------------------------------
Attachment: NHBugRepro.zip
I've created an example for what I believe to be this bug (or at least related). It happens in every version of NHibernate I have tested, from NH3.0GA through to NH3.2Alpha3.
The bug occurs if you pass it a projection expression with the same structure twice, where the projection is a method on an object. The second time you call it, it will execute the method on the first object you passed in, which it appears to have cached. This incorrect behaviour appears to persist for the whole lifetime of the session factory, not just the current session or transaction. Hanging onto user objects could be a bit memory wasteful too..
var foos1 = s.Query<Foo>().Select(x => selector1.Map(x));
var foos2 = s.Query<Foo>().Select(x => selector2.Map(x)); // does the same as foos1
var foos3 = s.Query<Foo>().Select(selector2.Map); // works fine
= Expected output =
S1:Test 1; S1:Test 2
S2:Test 1; S2:Test 2
S2:Test 1; S2:Test 2
= Actual output =
S1:Test 1; S1:Test 2
S1:Test 1; S1:Test 2
S2:Test 1; S2:Test 2
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Assignee: Patrick Earl
> Priority: Critical
> Attachments: NH-2500.patch, NHBugRepro.zip, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|
|
From: Cameron H. (JIRA) <nh...@gm...> - 2011-05-10 13:04:55
|
[ http://216.121.112.228/browse/NH-2500?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Cameron Harris updated NH-2500:
-------------------------------
Attachment: NH2500.zip
Attached a test-case as per welcome message. Does the same as my test program above.
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls.
> -------------------------------------------------------------------------------
>
> Key: NH-2500
> URL: http://216.121.112.228/browse/NH-2500
> Project: NHibernate
> Issue Type: Bug
> Components: Linq Provider
> Affects Versions: 3.0.0.GA
> Reporter: Andrey Titov
> Assignee: Patrick Earl
> Priority: Critical
> Attachments: NH-2500.patch, NH2500.zip, NHBugRepro.zip, NHTest3.zip
>
>
> NH 3.0 Linq provider uses query parameters from first call in subsequent calls if this parameters are not propagated to SQL.
> //in first session
> this.number = 545;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // all works perfect: all CatInfos contains 545
> //later in another session
> this.number = 842;
> var cats = session.Query<Cat>().Select(cat => new CatInfo { Name = cat.Name, SomeNumber = this.number }).ToList();
> // magic happens: all CatInfos contains 545 again
> I've debugged NH and found that in second query it gets QueryPlan from cache in NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan() and it contains parameters from first call of query (NHibernate.Linq.NhLinqExpression.ParameterValuesByName) and then fails to replace them in NHibernate.Linq.NhQueryProvider.SetParameters() because they are not actual SQL parameters (query.NamedParameters).
> Sample solution is attached (VS2010, SQL Server Express DB). Put NH and LinFu.DynamicProxy binaries to .Libraries\NHibernate before build.
> I think actual parameters should be cleared from query (set to default(T)) before putting plan in QueryPlanCache to let them be garbage collected and prevent real magic happen in case of similar bugs.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|