in reply to •Re^3: DB persistence framework for Perl Classes
in thread DB persistence framework for Perl Classes

Some Larry words:
  • ...To not try to discourage people from trying variances. We do not want to stabelish one church, we want to stabelish many denominations...
  • Sincerely I have never used Class::DBI in a deep way, and I will be glad if you can show me how to do what I'm trying to do here with Class::DBI, and if I think that something is missing I will add to Class::DBI as I have added to other modules.

    About lines of code, well, for me lines matters, specially for Perl, since we don't have a nice IDE with wizards like in Java were we really don't need to write things. Perl means write your own code.

    And about the portability of Class::DBI, I can be wrong, but you are saying to me that DBI is portable over databases. Well, the SQL is not.

    About my time, I'm paid to create components that help our development.

    Graciliano M. P.
    "Creativity is the expression of the liberty".

    • Comment on Re^4: DB persistence framework for Perl Classes

    Replies are listed 'Best First'.
    Re^5: DB persistence framework for Perl Classes
    by tadamec (Beadle) on Oct 18, 2004 at 01:40 UTC
      And about the portability of Class::DBI, I can be wrong, but you are saying to me that DBI is portable over databases. Well, the SQL is not.

      As somebody who fell into the "gotta write my own abstraction layer" trap, I have to disagree here.

      Class::DBI exists to allow you to not write SQL; problems with database portability I've run into have been limitations in the DBD layer of DBI and not related to Class::DBI directly. A good example of this is trying to access MS SQL Server; DBD::Sybase doesn't support bind parameters using the FreeTDS library.

      Code like this:

      my $item = db::Inventory::Item->retrieve( 15 ); if( $item ) { $item->quantity( 15 ); }
      works with every database I've tried so far where a Class::DBI driver exists.

      If you're worried about database portability, you have to take into account variants of "sequence" methodologies across various databases. For example, both Postgres and Oracle have an object called a sequence, but they access them differently:

      -- Oracle: INSERT INTO my_table VALUES( my_sequence.nextval, 'Some Value' ); -- Postgres: INSERT INTO my_table VALUES( nextval( 'my_sequence' ), 'Some Value' );
      Heaven forbid you want to use a database where sequences don't exist but you want autoincrementing fields, say MySQL or SQL Server/Sybase:
      --MySQL INSERT INTO my_table( seq_field, val_field ) VALUES (NULL, 'Some Value'); SELECT LAST_INSERT_ID(); -- SQL Server INSERT INTO my_table( val_field ) VALUES ( 'Some Value' ); SELECT SCOPE_IDENTITY();
      Not to mention that MySQL will insert a requested value into the sequence field (if it doesn't violate a primary key constraint), where SQL Server will barf if you attempt to place any value into an autoincrementing field.

      The code to do this with Class::DBI is exactly the same, no matter what database layer you deal with:

      my $newRecord = db::Table->create( { val_field => 'Some Value' } );
      And you don't have to deal with rewriting your SQL to handle different funkiness associated with different back ends. It Just Works.

      Granted, there are things I don't like about Class::DBI:

      • No really nice way to handle views
      • Docs for dealing with different connection settings are, shall we say, sparse. I still can't figure out how to have one set of user/password fields for, say, a web application and another for the command-line processing without duplicating the whole hierarchy
      • Relationships can be a bit funky to deal with.
      • Transaction support is really funky for long-running processes like mod_perl where you might want some records acted upon immediately and others batched

      What I tend to do is use Class::DBI for my user-type interactions where editing and small selection is involved (update my user preferences, edit an item, etc.) and use raw SQL for reporting in the web environment.

      For back-end batch processing, I tend to do everything with raw DBI/Perl code unless I have to iterate over every single record and the queries driving my main batch loop aren't JOINed tables.

        Views are basically handled as tables in Class::DBI. If you're really saying that you want to access an ad hoc query as a Class::DBI object, I would suggest that is reporting and should not be done through Class::DBI. Class::DBI is mostly helpful for read/write applications, not for simple query-and-display jobs.

        Having separate user/pass options is usually pretty straightforward with Class::DBI when you aren't trying to use them with the same class names inside the same running perl process. If you can expand on the problem you're having, there might be an easy answer.

        Your last comment about transaction support sounds interesting, but I'm not quite sure what you mean by it. Are you saying that you want to update some objects and then commit some of your changes but not all of them?

          Are you saying that you want to update some objects and then commit some of your changes but not all of them?

          Nope. Just plain old, simple transactions.

          Say, for example, I'd like to update 10,000 records in a database from a command-line script and I'd also like to read/update one record at a time in a web page. Currently, I have two different Class::DBI ancestors to handle the one-off changes, and another to handle batching the mass updates into smaller chunks so the transaction logs in the database don't get hammered.

          Some of my problems stem, I'm sure, from enforcing least-privilege at the database and application levels; my Apache database user has privileges to update a very limited set of tables and can read almost all the tables, where the command line processes can update most tables. The web user updates one record at a time, while the command line process almost always updates in large batches.

          Class::DBI seems to get confused in the Apache environment if I have transactions enabled in the Web base class and I haven't figured out a way around this other than doing a $obj->dbi_commit() after every read. This is, in my opinion, really a Bad Idea, as you shouldn't commit a record that you haven't changed and probably don't have write access to begin with.

    •Re^5: DB persistence framework for Perl Classes
    by merlyn (Sage) on Oct 17, 2004 at 20:04 UTC
      I have no problem with you reinventing the wheel if you've already studied other wheels. It's now clear that you haven't. Please study Class::DBI. Do not reinvent it without first figuring out exactly why it won't work for you.

      And it's not your time I care about (very much). It's the time it'll take the next guy to sort out your tiny implementation from the others that are on the CPAN. You waste everyone's time when you upload stuff that could have been done so much easier, had you just taken the time to know what already exists.

      The SQL used by Class::DBI is in fact portable to that list I've already given. Please to not be confusing issues here.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

    Re^5: DB persistence framework for Perl Classes
    by dragonchild (Archbishop) on Oct 17, 2004 at 22:07 UTC
      About lines of code, well, for me lines matters, specially for Perl, since we don't have a nice IDE with wizards like in Java were we really don't need to write things. Perl means write your own code.

      You and merlyn are talking past each other. merlyn, AFAICT, is talking about the number of lines in the distributions being used. You, AFAICT, are talking about the number of lines you need to use in order to stitch together the distributions. Two completely different things.

      As for IDEs ... it sounds like you really haven't used Java if you feel you can say such things. Granted, I haven't either, but people whose skills I trust have and, frankly, I don't think it's as you make out. Plus, if you use ActiveState, you have Komodo which is a full-fledged Perl IDE with almost as many features as Visual Studio.

      Perl means write your own code.

      You are taking a position here without thinking it through.. Frankly, Perl, to me, means don't write your own code! One of the primary reasons I use Perl is the existence of CPAN. Millions of lines of code, that I did not write, that I can plug straight into any project I am working on. In fact, not only did I not write it, but I don't maintain it. Even better!

      About my time, I'm paid to create components that help our development.

      That's funny. That's exactly what I'm paid to do, too. And, frankly, I work solely on the components that, after researching the topic as thoroughly as I can, I cannot find a CPAN module to do it. If the component has a serious impact upon our development, I estimate a good amount of hours to do it. If I can find some CPAN module that does it for me, I can goof off the rest of the time. Perl hackers are "Lazy", remember? :-)

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.