I really like the idea for using triggers to take care for versioning. However 
I'll evaluate both perl and SQL-based versioning because existing 
infrastructure relies on MySQL 4.1.

The thing I was missing is that "products" Manager class can use 
"products_history" manager to get the data for given revision. 

Since I intend to have versioning in the whole project, I need to keep correct 
foreign relation (e.g. products -> vendors) for each revision. I think I can 
achive this using compound "id+rev" foreign key. However I'm not sure if 
Manager handles such cases when builing JOINs. 


Thank you again to all of you guys for sharing your exprience!  I'll let you 
know when I have practical progress on this (it is in early stage of design)


On Monday 29 May 2006 22:23, John Siracusa wrote:
> On 5/29/06 6:21 AM, Svilen Ivanov wrote:
> > I would like to extend RDBO to support versioning of properties for each
> > instance. To explain it better I will use analogy with CVS:
> > * calling "->save" will make new revision of the object ("cvs commit")
> > * "->load(id=>1)" will get by default the latest version ("cvs checkout")
> > * "->load(id=>1, rev => 5)" will get the fifth revison of this particular
> > instance ("cvs -r 1.5 checkout")
> > The ultimate goal is to have ability to rollback the objects to their
> > state at a specific point of time in the past. It would be the best if I
> > can do it as layer on top of existing RDBO.
>
> I've done this a few different ways in the past.  The "safest" way, IME, is
> to let the database do almost all of the work, and then do the rest
> "manually" on the RDBO side.  This requires a database with triggers and
> transactions.  Here's the setup.
>
> 1. Create a table called "products" with the normal columns you need.
> (i.e., no special columns for versioning)
>
> 2. Create a "products_history" table with the same columns as the
> "products" table, and a few more columns for versioning.  You can use
> dates, revision integers, whatever you want.
>
> 3. Set up triggers for the products table on insert and update.  For both
> events, insert a new row in the products_history before inserting or
> updating a row in the products table.  The new products_history row should
> be an exact copy of the products row before an update operation, or an
> exact copy of the new products row during an insert operation, but with the
> addition of the versioning columns.
>
> 4. Make RDBO classes for the products and products_history tables in the
> normal manner.
>
> Advantages of this approach:
>
> * The products and products_history tables are always in sync and
> consistent, no matter how the database is updated.
>
> * It's very clear what things do from the RDBO side.  There's nothing
> special about the RDBO classes at all.
>
> * The performance of "current" data is not very different than if you were
> not doing any versioning at all.  IOW, the product table only contains the
> most recent revisions, and is therefore as small as possible.  All the
> "bloat" goes in the products_history  table.
>
> Disadvantages:
>
> * You must use a different class when you want to look at historic data.
>
> If you need to know what revision the "current" version is, you can also
> put the versioning columns in the "products" table.
>
> If you want to make this more transparent from the Perl side, or if you're
> forced to use a database without trigger support and transactions, try this
> approach:
>
> 1. Set up two tables as described above, sans triggers.
>
> 2. Set up two RDBO classes for those tables in the usual manner.
>
> 3. Modify the class that fronts the "products" table in the following ways:
>
> 3.1 Add attributes for your versioning data.  Don't add actual columns,
> just make the accessor methods.
>
> 3.2 Override load().  If a versioning attribute is set, load from the
> products_history table using the RDBO class that fronts it, then "suck out"
> all the column data and stick it in the current object.  Then discard the
> products_history object.
>
> 3.3 Override save().  On save, start a transaction and create a new row in
> the products_history table using the appropriate RDBO class, pushing the
> column values from the current object into the history object.  Then save
> the current object into the products table and commit the transaction.
>
> 4. Modify the manager's get_objects() method.  If versioning data is
> specified in the query, call the products_history manager instead.
> Otherwise, call the regular superclass method.
>
> I glossed over a lot of details there, but the idea is to do on the Perl
> side what was done in the triggers in the earlier setup.  As usual, there
> are many different ways to do this.  I've just (briefly) described two
> ways. I'm sure you can come up with more :)
>
> -John


-------------------------------------------------------
All the advantages of Linux Managed Hosting--Without the Cost and Risk!
Fully trained technicians. The highest number of Red Hat certifications in
the hosting industry. Fanatical Support. Click to learn more
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to