You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently it is impossible to use a find({ association: instance }) condition correctly, as such conditions are passed directly to node-sql-query without any kind of intelligent filtering.
Repro
varperson=db.define('person',{name: String});varpet=db.define('pet',{name: String});pet.hasOne('owner',person,{required: true});// Load some stuff into the database...person.get(1,function(err,person){pet.find({owner: person},function(err,pets){// Generates an invalid SQL query});});
Problem
Instead of using owner_id, and the id of the passed person, to run the query (as one would expect) we find node-orm2 passing the conditions in raw form to node-sql-query (not sql-query's fault, since it is supposed to be low level) which results in a SQL query like the following:
Preprocess conditions as they are received, mapping conditions who's identifiers map to properties on the current model to the identifiers required to identify the relationship.
Preprocess conditions, mapping if the value of a condition is an Instance object and the condition identifier maps to a property on the current model.
Ah, was also looking into it. Appears somewhat more complicated to fix nicely than I first expected - since conditions can also be used in table joins, and there doesn't appear to be any central point that they all pass through.
Currently working on adding a method to Model which preprocesses conditions, and then I'll try to get merge options to pass through that as well (or something similar).
It also appears that this only affects hasOne associations, since hasMany and extendsTo don't appear to add properties which could be used as conditions.
I'm just pointing my batteries to hasOne associations. I'm just going to update to support Array of instances. Other things can then be added and this function used in more places.
Hmm, just looked through your implementation fully and looks like there is currently no support for multiple primary keys. Unfortunately, adding support for multiple values AND primary keys requires that we add some additional functionality to node-sql-query.
Basically, if we want to support something like this
Pet.find({owner: [owner1,owner2]},function(err,pets){//pets with either owner1 or owner2 as their owner, implied by same syntax as { owner_id: [owner1.id, owner2.id] }});
we would need to add support for generating of a SQL query like
SELECT*FROM`pets`WHERE (`owner_id1`=`1`AND`owner_id2`=`1`) OR (`owner_id1`=`2`AND`owner_id2`=`2`)
My proposal would be for a custom conditions object which provides logical handling along the lines of
Thus, it should support chaining on the and and or methods, and support either anonymous condition objects (as the current implementation uses) or other ORM.conditions instances to allow for complex conditional queries.
The and and or methods should wrap their conditions in brackets when generating the query, unless only one key is present in the condition, in which case it should be added to the previous condition set (if it's of the same type - AND + AND = AND, OR + OR = OR, AND(x) + OR(y) = (x) OR (y))
varconditions=ORM.conditions({name: 'John'});// `name` = 'John'conditions=conditions.and({surname: 'Doe'});// `name` = 'John' AND `surname` = 'Doe'conditions=conditions.or({name: 'Sally',surname: 'Black'});// (`name` = 'John' AND `surname` = 'Doe') OR (`name` = 'Sally' AND `surname` = 'Black')
Okay, let me do that instead then. Having issues at the moment getting tests to pass for SQLite, it appears to dislike returning a valid owner object when matching on pet_id (although all the other DB engines appear to work so far). Been bashing my head against a wall for hours on it, and can't seem to figure out the problem (doesn't help that node-sqlite won't build on my local machine)
Hmm, okay. Also looks like MongoDB automatically increments that ID on changes to the model - which makes some of the tests in my suite fail. I'm tempted to just check the name property (which is unique in this case) but it doesn't solve the underlying issue.
Well here's the test I was running, and _id was being incremented on the same model by the looks of it.
varsetup=function(){returnfunction(done){Person=db.define('person',{name : String});Pet=db.define('pet',{name : String});Person.hasOne('pet',Pet,{reverse: 'owner',field: 'pet_id'});returnhelper.dropSync([Person,Pet],function(){async.parallel([Person.create.bind(Person,{name: "John Doe"}),Person.create.bind(Person,{name: "Jane Doe"}),Pet.create.bind(Pet,{name: "Deco"}),Pet.create.bind(Pet,{name: "Fido"}),],done);});};};// Other tests...it("should be able to find given an association instance",function(done){Person.find({name: "John Doe"}).first(function(err,John){should.not.exist(err);should.exist(John);Pet.find({name: "Deco"}).first(function(err,Deco){should.not.exist(err);should.exist(Deco);Deco.hasOwner(function(err,has_owner){should.not.exist(err);has_owner.should.be.false;Deco.setOwner(John,function(err){should.not.exist(err);Person.find({pet: Deco}).first(function(err,owner){should.not.exist(err);should.exist(owner);should.equal(owner[Person.id[0]],John[Person.id[0]]);done();});});});});});});// And 2 other tests which are variants thereof
The Person.id[0] is just to get id for *SQL and _id for MongoDB. If you can spot anything in there which would be recreating the instances on Mongo (but not SQL) then let me know and I'll change it, otherwise we may have a bug in our Mongo implementation...
Okay, I think we can mark this as resolved as of the latest code in master. We currently handle both multiple instance and multiple identifier key query generation, and haven't had any test failures as a result of the new code.
If any issues are found then we'll re-open this, but in the mean time I'm gonna close it.
Activity
dresende commentedon Aug 8, 2013
I'm working on this right now.
notheotherben commentedon Aug 8, 2013
Ah, was also looking into it. Appears somewhat more complicated to fix nicely than I first expected - since conditions can also be used in table joins, and there doesn't appear to be any central point that they all pass through.
Currently working on adding a method to Model which preprocesses conditions, and then I'll try to get merge options to pass through that as well (or something similar).
It also appears that this only affects
hasOneassociations, sincehasManyandextendsTodon't appear to add properties which could be used as conditions.Adds instance.model() to get the model of an instance (#293)
Adds Utilities.checkConditions() (#293)
dresende commentedon Aug 8, 2013
I'm just pointing my batteries to hasOne associations. I'm just going to update to support
Arrayof instances. Other things can then be added and this function used in more places.Adds support for Array of instances
Adds instance.model() to get the model of an instance (dresende#293)
Adds Utilities.checkConditions() (dresende#293)
notheotherben commentedon Aug 8, 2013
Appears to be working correctly for
hasOnerelationships, I'll look into adding support forhasManyandextendsTowhen I get the chance.dresende commentedon Aug 10, 2013
Please add some tests if you have time :)
notheotherben commentedon Aug 10, 2013
Will do
Add tests for dresende#293
notheotherben commentedon Aug 10, 2013
Hmm, just looked through your implementation fully and looks like there is currently no support for multiple primary keys. Unfortunately, adding support for multiple values AND primary keys requires that we add some additional functionality to node-sql-query.
Basically, if we want to support something like this
we would need to add support for generating of a SQL query like
My proposal would be for a custom conditions object which provides logical handling along the lines of
Thus, it should support chaining on the
andandormethods, and support either anonymous condition objects (as the current implementation uses) or other ORM.conditions instances to allow for complex conditional queries.The
andandormethods should wrap their conditions in brackets when generating the query, unless only one key is present in the condition, in which case it should be added to the previous condition set (if it's of the same type - AND + AND = AND, OR + OR = OR, AND(x) + OR(y) = (x) OR (y))Rewrote utils.checkConditions dresende#293
Rewrote utils.checkConditions dresende#293
8 remaining items
dresende commentedon Aug 10, 2013
I think it's OK for now, but you can create an uid value or something (like Instance has using
hatmodule).notheotherben commentedon Aug 10, 2013
Okay, let me do that instead then. Having issues at the moment getting tests to pass for SQLite, it appears to dislike returning a valid owner object when matching on
pet_id(although all the other DB engines appear to work so far). Been bashing my head against a wall for hours on it, and can't seem to figure out the problem (doesn't help that node-sqlite won't build on my local machine)Add Model.uid (dresende#293)
Attempt to fix SQLite test failures (dresende#293)
Fix SQLite and MongoDB test failures (dresende#293)
Fix SQLite and MongoDB test failures (dresende#293)
notheotherben commentedon Aug 10, 2013
Okay, another question: Why are we using a different primarykey format for MongoDB?
Fix SQLite and MongoDB test failures (dresende#293)
dresende commentedon Aug 11, 2013
MongoDB default id is "_id" (automatically added). I don't have enough experience to know how to change this name.
notheotherben commentedon Aug 11, 2013
Hmm, okay. Also looks like MongoDB automatically increments that ID on changes to the model - which makes some of the tests in my suite fail. I'm tempted to just check the
nameproperty (which is unique in this case) but it doesn't solve the underlying issue.dresende commentedon Aug 11, 2013
The _id does never change. If it's changing it might be because of recreating instances.
notheotherben commentedon Aug 12, 2013
Well here's the test I was running, and _id was being incremented on the same model by the looks of it.
The
Person.id[0]is just to getidfor *SQL and_idfor MongoDB. If you can spot anything in there which would be recreating the instances on Mongo (but not SQL) then let me know and I'll change it, otherwise we may have a bug in our Mongo implementation...Fix SQLite and MongoDB test failures (dresende#293)
notheotherben commentedon Aug 18, 2013
Okay, I think we can mark this as resolved as of the latest code in master. We currently handle both multiple instance and multiple identifier key query generation, and haven't had any test failures as a result of the new code.
If any issues are found then we'll re-open this, but in the mean time I'm gonna close it.