Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Sun, Oct 5, 2008 at 12:22 PM, Matt S Trout [EMAIL PROTECTED] wrote: On Thu, Oct 02, 2008 at 08:18:59AM +0100, Carl Franks wrote: 2008/10/2 Zbigniew Lukasiak [EMAIL PROTECTED]: On Thu, Oct 2, 2008 at 2:40 AM, Matt S Trout [EMAIL PROTECTED] wrote: On Wed, Oct 01, 2008 at 09:38:07AM +0200, Zbigniew Lukasiak wrote: The example that I am mostly concerned with is: $cd_rs-recursive_update( { title = 'New Title', artist = { name = 'New Name' } } ) Now when traversing the relation from cd to the artist I get the artist resultset with the PK constrained in the -{cond}. There is just one artist that the cd 'belongs_to' - and that artist should be updated. But there is no PK passed in the parameters - so if we just look at the parameters we would conclude that this would require a -create call. Ah, because the artist is about to be changed? In that case you should create the artist separately and then assign it I think, which again avoids the problem. Perhaps I did not explain it enough - I want that call to result in an update not a create. An update to the only artist that 'belongs_to' the cd. ( /me steps into a minefield ) I would suggest that if it's an update, you should already have the artist PK - keep ahold of it when you're initially getting the vales from the DB. Then, when you're doing the update, verify the PK hasn't changed (or maybe allow it to be configured to allow rel ID changes). I know FormFu doesn't do that, it can just follow the relationship name, so you don't need a hidden field for the related PK - but I feel it's more flexible to handle traversing the relationships ourselves, rather than using a core DBIC recursive-update. Especially given there are probably multiple different behaviours you'll want in different situations. I am curious about those different behaviours - what do you have on mind? Ad PK - it is in the relationship - this is a 'belongs_to' after all - I don't want to require the user of the libarary to have to worry about it. Cheers, Zbigniew http://brudnopis.blogspot.com/ http://perlalchemy.blogspot.com/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
2008/10/2 Zbigniew Lukasiak [EMAIL PROTECTED]: On Thu, Oct 2, 2008 at 2:40 AM, Matt S Trout [EMAIL PROTECTED] wrote: On Wed, Oct 01, 2008 at 09:38:07AM +0200, Zbigniew Lukasiak wrote: The example that I am mostly concerned with is: $cd_rs-recursive_update( { title = 'New Title', artist = { name = 'New Name' } } ) Now when traversing the relation from cd to the artist I get the artist resultset with the PK constrained in the -{cond}. There is just one artist that the cd 'belongs_to' - and that artist should be updated. But there is no PK passed in the parameters - so if we just look at the parameters we would conclude that this would require a -create call. Ah, because the artist is about to be changed? In that case you should create the artist separately and then assign it I think, which again avoids the problem. Perhaps I did not explain it enough - I want that call to result in an update not a create. An update to the only artist that 'belongs_to' the cd. ( /me steps into a minefield ) I would suggest that if it's an update, you should already have the artist PK - keep ahold of it when you're initially getting the vales from the DB. Then, when you're doing the update, verify the PK hasn't changed (or maybe allow it to be configured to allow rel ID changes). I know FormFu doesn't do that, it can just follow the relationship name, so you don't need a hidden field for the related PK - but I feel it's more flexible to handle traversing the relationships ourselves, rather than using a core DBIC recursive-update. Carl ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Wed, Oct 1, 2008 at 3:17 AM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 02:39:00PM +0200, Zbigniew Lukasiak wrote: On Tue, Sep 30, 2008 at 2:20 PM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 09:28:50AM +0200, Zbigniew Lukasiak wrote: The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. Well, yes. If you have an auto-increment PK and you don't have a value for it, then (1) there's no form field in the first place, so that's not an issue (2) you know you can't possibly find anything, so you wouldn't call update_or_create, you'd just call create I presume this is what Oliver's doing, which is why his code works. Nothing tricky at all. This method assumes that you don't get the PK in the ResultSet in the internal conditions. I is ok if you have the full controll over the ResultSet - but if you do admit this possibility (for example when you traverse a belongs_to relation, or if you use RestrictedWithObject) - then you would have to inspect it o check what part of the PK is there to decide if you should go directly to -create. Since currently there is no easy and sound way of doing this inspection (and for some, rather convoluted - I admit, cases it is impossible - that is it is undecidable - i.e. cannot be solved by an algorithm) - this makes this method unsuitable for my purposes. I don't see that this would ever happen with an auto-inc PK though. And if it's a unique key, the behaviour is rather different. Basically, I've not yet seen a real world example where this situation actually comes up, and I can't think of a contrived one that doesn't come into the category of your design is broken. So it's so far a problem in theory but not in practice - can you provide a real example of this situation? The example that I am mostly concerned with is: $cd_rs-recursive_update( { title = 'New Title', artist = { name = 'New Name' } } ) Now when traversing the relation from cd to the artist I get the artist resultset with the PK constrained in the -{cond}. There is just one artist that the cd 'belongs_to' - and that artist should be updated. But there is no PK passed in the parameters - so if we just look at the parameters we would conclude that this would require a -create call. If someone uses add_relationship instead of the ('belongs_to' or 'might_have' ) helpers - this becomes even more untraceable. For a slightly more contrived example let's take User and Notes just as you have at: http://search.cpan.org/~groditi/DBIx-Class-Schema-RestrictWithObject-0.0001/lib/DBIx/Class/Schema/RestrictWithObject.pm , but let's assume that the Notes table has a composite primary key that contains 'user_id' and 'subject'. Then one would expect that this: $restricted_notes_rs-update_or_create( { subject = 'Some existing subject', some_other_column = 'New Value' } ) would result in updating the Notes record with ( $user_id, 'Some existing subject' ) in PK rather then trying (and failing) to create a new record. -- Zbigniew Lukasiak http://brudnopis.blogspot.com/ http://perlalchemy.blogspot.com/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Wed, Oct 01, 2008 at 09:38:07AM +0200, Zbigniew Lukasiak wrote: On Wed, Oct 1, 2008 at 3:17 AM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 02:39:00PM +0200, Zbigniew Lukasiak wrote: On Tue, Sep 30, 2008 at 2:20 PM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 09:28:50AM +0200, Zbigniew Lukasiak wrote: The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. Well, yes. If you have an auto-increment PK and you don't have a value for it, then (1) there's no form field in the first place, so that's not an issue (2) you know you can't possibly find anything, so you wouldn't call update_or_create, you'd just call create I presume this is what Oliver's doing, which is why his code works. Nothing tricky at all. This method assumes that you don't get the PK in the ResultSet in the internal conditions. I is ok if you have the full controll over the ResultSet - but if you do admit this possibility (for example when you traverse a belongs_to relation, or if you use RestrictedWithObject) - then you would have to inspect it o check what part of the PK is there to decide if you should go directly to -create. Since currently there is no easy and sound way of doing this inspection (and for some, rather convoluted - I admit, cases it is impossible - that is it is undecidable - i.e. cannot be solved by an algorithm) - this makes this method unsuitable for my purposes. I don't see that this would ever happen with an auto-inc PK though. And if it's a unique key, the behaviour is rather different. Basically, I've not yet seen a real world example where this situation actually comes up, and I can't think of a contrived one that doesn't come into the category of your design is broken. So it's so far a problem in theory but not in practice - can you provide a real example of this situation? The example that I am mostly concerned with is: $cd_rs-recursive_update( { title = 'New Title', artist = { name = 'New Name' } } ) Now when traversing the relation from cd to the artist I get the artist resultset with the PK constrained in the -{cond}. There is just one artist that the cd 'belongs_to' - and that artist should be updated. But there is no PK passed in the parameters - so if we just look at the parameters we would conclude that this would require a -create call. Ah, because the artist is about to be changed? In that case you should create the artist separately and then assign it I think, which again avoids the problem. Better ideas welcome. -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Mon, Sep 29, 2008 at 11:40 PM, Oliver Gorwits [EMAIL PROTECTED] wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Zbigniew Lukasiak wrote: It works only with primary keys. And if you supply 'undef' in the place of the auto_increment PK then it knows that this will be a new row. This is an additional convention that I add over the DBIC semantics - I don't insist that it is elegant but without it I would have two options: - an additional parameter to specify if the operation on a given row is an update or a create - require that the user adds additional constraints Here's pseudocode for what I do in LFB: # eval{ search for row with PK(s) matching user data PK(s) } # if result is blessed # then user is asking for an update, so do set_columns # else, # user is asking for new row, so do new_result # do update_or_insert. No PK hint is required, here. In the case where there aren't auto-generated PK values, and the user supplies them, then the eval{} still fails, causing a new_result. So you say that you call -find( { pk = undef, ... } ) ( or -search( { pk = undef } )-next ) in that case? This works of course - it will not find any row - just as you need and this is exactly what I do in recursive_update - as described above. The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. What scenario is missing from the above, I'd be interested to know ? -- Zbigniew Lukasiak http://brudnopis.blogspot.com/ http://perlalchemy.blogspot.com/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Tue, Sep 30, 2008 at 09:28:50AM +0200, Zbigniew Lukasiak wrote: The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. Well, yes. If you have an auto-increment PK and you don't have a value for it, then (1) there's no form field in the first place, so that's not an issue (2) you know you can't possibly find anything, so you wouldn't call update_or_create, you'd just call create I presume this is what Oliver's doing, which is why his code works. Nothing tricky at all. FormFu didn't used to do this, but Carl Franks agreed with me that this was a bug in FormFu. If your code still has this bug, I suggest you fix it. -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Tue, Sep 30, 2008 at 2:20 PM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 09:28:50AM +0200, Zbigniew Lukasiak wrote: The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. Well, yes. If you have an auto-increment PK and you don't have a value for it, then (1) there's no form field in the first place, so that's not an issue (2) you know you can't possibly find anything, so you wouldn't call update_or_create, you'd just call create I presume this is what Oliver's doing, which is why his code works. Nothing tricky at all. This method assumes that you don't get the PK in the ResultSet in the internal conditions. I is ok if you have the full controll over the ResultSet - but if you do admit this possibility (for example when you traverse a belongs_to relation, or if you use RestrictedWithObject) - then you would have to inspect it o check what part of the PK is there to decide if you should go directly to -create. Since currently there is no easy and sound way of doing this inspection (and for some, rather convoluted - I admit, cases it is impossible - that is it is undecidable - i.e. cannot be solved by an algorithm) - this makes this method unsuitable for my purposes. FormFu didn't used to do this, but Carl Franks agreed with me that this was a bug in FormFu. If your code still has this bug, I suggest you fix it. What is a bug for you? -- Zbigniew Lukasiak http://brudnopis.blogspot.com/ http://perlalchemy.blogspot.com/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
OK - so here is an improved reply. On Tue, Sep 30, 2008 at 2:39 PM, Zbigniew Lukasiak [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 2:20 PM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 09:28:50AM +0200, Zbigniew Lukasiak wrote: The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. Well, yes. If you have an auto-increment PK and you don't have a value for it, then (1) there's no form field in the first place, so that's not an issue (2) you know you can't possibly find anything, so you wouldn't call update_or_create, you'd just call create I presume this is what Oliver's doing, which is why his code works. Nothing tricky at all. This method assumes that you don't get the PK in the ResultSet in the internal conditions. I is ok if you have the full controll over the ResultSet - but if you do admit this possibility (for example when you traverse a belongs_to relation, or if you use RestrictedWithObject) - then you would have to inspect it o check what part of the PK is there to decide if you should go directly to -create. Since currently there is no easy and sound way of doing this inspection (and for some, rather convoluted - I admit, cases it is impossible - that is it is undecidable - i.e. cannot be solved by an algorithm) - this makes this method unsuitable for my purposes. If we don't care about all possible predicates resulting in a unique constraint on the PK - and only count the equalities (that is 'pk = 1' is filtered out, 'pk = 2' stays) - then it is obviously decidable. If $rs-{cond} is a normal SQL::Abstract structure then it should not be that difficult to write this PK checker. I know you decided that this can wait for the 0.9 version - but if you changed your mind I think I can write that. For the time being the convention with special treatment for {pk = undef} is the only way that I can implement something covering all the possible cases. -- Zbigniew Lukasiak http://brudnopis.blogspot.com/ http://perlalchemy.blogspot.com/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Zbigniew Lukasiak wrote: For the time being the convention with special treatment for {pk = undef} is the only way that I can implement something covering all the possible cases. I think that special treatment should set off alarm bells in your head. It's a sign that either this is a path to insanity, or just incorrect design which will not scale. To my mind the best thing to do would be drop the requirement to cater for all possible cases - after all that's not what Perl/CPAN is about; it's about catering for a set of cases for *some* systems, and somebody else can deal with the other cases. The PK = undef hint is just that, a hint, and hints are by definition disposable, hence not required, and therefore not necessary. - -- Oliver Gorwits, Network and Telecommunications Group, Oxford University Computing Services -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI4rOt2NPq7pwWBt4RAstAAJ4jzqwJhmPOCGcSN2aY1SxS+QnNAQCg0mZY JNPISfcn+IryZdIFxSERRqI= =bk1N -END PGP SIGNATURE- ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
On Tue, Sep 30, 2008 at 02:39:00PM +0200, Zbigniew Lukasiak wrote: On Tue, Sep 30, 2008 at 2:20 PM, Matt S Trout [EMAIL PROTECTED] wrote: On Tue, Sep 30, 2008 at 09:28:50AM +0200, Zbigniew Lukasiak wrote: The tricky part is when you load data from the form into the new row. You need to delete the pk from it - because otherwise at update_or_insert time it would issue an insert with pk = NULL - and this will fail in Pg (for example). The point is that you cannot feed the same data to the find and to the insert calls - but update_or_create does that - and why it does not have much choice is another very long story. Well, yes. If you have an auto-increment PK and you don't have a value for it, then (1) there's no form field in the first place, so that's not an issue (2) you know you can't possibly find anything, so you wouldn't call update_or_create, you'd just call create I presume this is what Oliver's doing, which is why his code works. Nothing tricky at all. This method assumes that you don't get the PK in the ResultSet in the internal conditions. I is ok if you have the full controll over the ResultSet - but if you do admit this possibility (for example when you traverse a belongs_to relation, or if you use RestrictedWithObject) - then you would have to inspect it o check what part of the PK is there to decide if you should go directly to -create. Since currently there is no easy and sound way of doing this inspection (and for some, rather convoluted - I admit, cases it is impossible - that is it is undecidable - i.e. cannot be solved by an algorithm) - this makes this method unsuitable for my purposes. I don't see that this would ever happen with an auto-inc PK though. And if it's a unique key, the behaviour is rather different. Basically, I've not yet seen a real world example where this situation actually comes up, and I can't think of a contrived one that doesn't come into the category of your design is broken. So it's so far a problem in theory but not in practice - can you provide a real example of this situation? -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Directorhttp://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/ ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]
Re: [Dbix-class] Re: DBIx::Class::ResultSet::RecursiveUpdate - announcement and RFC
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Zbigniew Lukasiak wrote: It works only with primary keys. And if you supply 'undef' in the place of the auto_increment PK then it knows that this will be a new row. This is an additional convention that I add over the DBIC semantics - I don't insist that it is elegant but without it I would have two options: - an additional parameter to specify if the operation on a given row is an update or a create - require that the user adds additional constraints Here's pseudocode for what I do in LFB: # eval{ search for row with PK(s) matching user data PK(s) } # if result is blessed # then user is asking for an update, so do set_columns # else, # user is asking for new row, so do new_result # do update_or_insert. No PK hint is required, here. In the case where there aren't auto-generated PK values, and the user supplies them, then the eval{} still fails, causing a new_result. What scenario is missing from the above, I'd be interested to know ? - -- Oliver Gorwits, Network and Telecommunications Group, Oxford University Computing Services -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI4UtG2NPq7pwWBt4RAmwlAJ4wmQpVjZwbi9yNB/wNZqJi6/vsqACglQxn /Z9wz44Kqbp6KZSbJpmDUK8= =vyLp -END PGP SIGNATURE- ___ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/ Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]