On 1/11/06 9:16 AM, Scott Karns wrote: > My current problem is that the database I'm working with contains two column > types that are specific to postgres and don't seem to be supported by RDBO. > The first I alluded to in an earlier message, the 'OID' column type that I am > using to store what amounts to blob data (an image file actually)
You can't just use a scalar column for that? What kind of special handling does it need? > and the second is a 'time' column type used to store class (as in school) > scheduling information. [...] After looking through some of the RDBO::Metadata > space, I believe my best bet is to create a new scalar column class that will > convert the Pg data to an integer upon access and back to the Pg form upon > store as well as some ability to play well with timestamp objects. I had Pg time types in a few early versions of RDBO, but I could never decide on a nice client-side representation. An integer seems like a strange choice to me. DateTime objects aren't really appropriate because time columns have no date information. I could just make one myself, I suppose. What I'm looking for is pretty simple: * Stringifies to an arbitrary strftime-like format (HH:MM:SS by default) * Has hour, minute, second, nanosecond, am/pm get/set methods. * Supports simple time math with wrap-around. Is such a thing lurking on CPAN anywhere? Remember, no dates! :) Anyway, although I'd prefer it if you created a new column class and method maker for a Time type as I describe above and then submitted it as a patch, here are two ways you might do what you describe instead (using an integer as the client-side representation.) The first option, as Svilen pointed out, is to use triggers. This will work, but it maybe tedious to apply those triggers to each of your time columns in each class. A more general solution is to make your own column class. The steps would be something like this: 1. Make your column class, e.g., My::DB::Column::PgTime. Inheriting from the Scalar column class is probably fine. 2. Map your column class to the column type name of your choice, either globally in Rose::DB::Object::Metadata, or locally in a metadata subclass of your own. I'm assuming you already have a common base class for all your db objects. If so, making a trivial custom metadata subclass and then setting your common base class's meta_class to this class name should be easy. You can see an example of setting up a custom metadata class here: http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object/ConventionMana ger.pm#TIPS_AND_TRICKS Either way, to make the mapping, use the column_type_class() method: http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object/Metadata.pm#co lumn_type_class Example: $meta->column_type_class(mypgtime => 'My::DB::Column::PgTime'); 3. Make a new method-maker for your column class that does the appropriate inflate/deflate stuff at the right times. The 'bitefield' method maker in Rose::DB::Object::MakeMethods::Generic is probably the simplest existing example. One caveat: you should definitely use the functions in Rose::DB::Object::Util to determine when you're save()ing, when you're load()ing, etc. The column classes bundled with RDBO use the undocumented internal methods to get this info (direct hash key access!) Don't do that in your classes since that's an implementation detail that may change at any time. When it does, RDBO itself will be updated, of course, but your custom column class will stop working. So remember: use public APIs only! :) Anyway, for details on how method makers work, check these docs: http://search.cpan.org/dist/Rose-Object/lib/Rose/Object/MakeMethods.pm 4. Point your column class at your new method maker. See the "protected API" for columns for an easy way to this: http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object/Metadata/Colum n.pm#PROTECTED_API 5. Finally, when you set up your classes, just use your newly-mapped column type name: __PACKAGE__->meta->columns ( ... start => { type => 'mypgtime', ... }, ); --- Hre's the overall flow inside RDBO starting with a column definition like the one above. 1. Get type name 'mypgtime' from hashref definition (or column object via the type() attribute). 2. Look up the corresponding class by calling $meta->column_type_class('mypgtime') using the metadata object for this class. 3. Make a new column object of that class, initializing it based on the rest of the params in the hashref (+/- some massaging) <...time passes...> 4. Inside the call to meta->initiaize(), make_methods() is called on the column object in order to make the accessor method(s) to service this column. To do this, the column object will call through to a method-maker. Although, technically, a column can do whatever it wants in response to make_methods(), RDBO uses Rose::Object::MakeMethods to do the work, and the Column base class has a bunch of configuration values that make it easy to point to a particular method maker of that type. Confused yet? :) If you really want to tackle it, just start at the beginning and take it a piece at a time. Or, if you can wait, then find me a nice time object on CPAN so I can add a default Time column type to RDBO. Then wait for the next release and just use that :) I keep meaning to write Rose::DB::Object::Extending.pod... -John ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click _______________________________________________ Rose-db-object mailing list Rose-db-object@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rose-db-object