From: Chris W. <ch...@cw...> - 2001-11-01 22:28:01
|
So after thinking about this problem of multiple-field primary keys for a while, I came up with what seems to be a decent solution. I'm still testing it out, but it seems to work well and I wanted to see if anyone had any thoughts before I charged ahead. First, I believe that the ID of an object should be a string or easily stringified. This is not only for us people who like to read such things, but SPOPS does a lot of work (security, for one) using the object class and ID value. (Caching will be the same way.) So with that in mind, here's some demo code: # This object uses three fields (field1, field2, field3) for the key, # and we delimit the values with commas to make a single string. We # will probably make the delimiter customizable. my $id = join( ',', $field1, $field2, $field3 ); my $obj = My::MultiFieldKey->fetch( $id ); # Retrieve the ID in scalar context: print "ID: (", scalar $obj->id, ")"; # >> ID: (45,99,ABCD) # Now retrieve the ID in list context my @val = $obj->id; # Values: $val[0] = 45; $val[1] = 99; $val[2] = 'ABCD'; # Display the SQL clause we use to uniquely retrieve, update and # remove this record print "WHERE ", $obj->id_clause; # >> WHERE table.field1 = 45 AND table.field2 = 99 AND \ # table.field3 = 'ABCD' # Get the ID fields in scalar context print "ID fields for object: ", scalar $obj->id_field, "\n"; # >> field1,field2,field3 # Get the ID fields in list context my @to_select = map { "$table.$_" }, @selected, $obj->id_field; What you need to do: - Specify the ID fields you want in your object configuration as an arrayref instead of a string: id_field => [ 'field1', 'field2', 'field3' ] That's it! Caveats: - You must always keep the ordering of the fields listed in 'id_field' of your configuration, or you'll break security and other object layers (full-text indexing, etc.). - You can link to objects in this class, but you can't use the 'has_a' type of relationship - I need to look at and modify something in the lazy loading implementation for SPOPS::DBI - If part of your multifield key is automatically generated (using a pre/post_id method such as with auto-increment/sequenced fields), then there *might* be some issues, but it will probably work fine. How it works: Two new class-factory behaviors in SPOPS::DBI treat an arrayref in the 'id_field' of a class configuration as a signal to generate the methods: id_field() id() id_clause() These are created at startup for a multiple field class, and then it's just like every other class. There are no modifications to the class hierarchy or anything else. (And classes using a single field for an ID aren't touched.) So I need to test this out some more and see how it works -- nothing like testing on live data! -- but if you have any ideas I'd love to hear them. I feel like there's something I'm missing.... Chris -- Chris Winters (ch...@cw...) Building enterprise-capable snack solutions since 1988. |