On Tue, Nov 29, 2005 at 04:05:26PM -0800, Tyler MacDonald wrote:
> Tim Bunce <[EMAIL PROTECTED]> wrote:
> > PostgreSQL is non-standard (and inconvenient) in this respect.
>
> I chatted with Mischa (my work's resident DB guru) about this, and
> according to him, the error behaviour when you attempt to SELECT from a
> table that does not exist is "undetermined" in the SQL standard, so it
> really is the individual DBMS' choice. I think that's actually worse; all of
> these DBMs are behaving completely differently but still "correctly" on such
> a basic SQL operation due to a lack of standard!
I was thinking more generally: the failure of a statement within a
transaction (such as an insert getting a duplicate key error) usually
rolls-back just that statement and does not abort the whole transaction.
If that's not true for PostgreSQL then that's certainly inconvenient.
> > There isn't, as far as I know, except to accept the 'lowest common
> > denominator'. In this case that means forcing a rollback if any
> > statement fails.
>
> > execute() is sufficient if the driver doesn't also supply it's own do()
> > because DBI's default do() calls execute(). But some drivers do supply
> > their own do() method (for good reasons).
>
> Fair enough. So what I've done, is modified DBIx::Transaction to
> mark a transaction error if any query in the transaction returns false;
>
> --snip--
> sub execute {
> my $self = shift;
> my $rv = eval { DBI::st::execute($self, @_); };
I'd probably say:
my $rv = eval { $self->SUPER::execute(@_) };
> if($@) {
> $self->{Database}->inc_transaction_error;
> die "[EMAIL PROTECTED]";
> }
> if(!$rv) {
> $self->{Database}->inc_transaction_error;
> }
> return $rv;
> }
> --snip--
>
> (and similar logic for db::do()).
>
> The package I'm working on that uses DBIx::Transaction now also
> checks for the existance of a table before attempting to manipulate it.
See note above. I think that's just one example of a more general issue.
> I was considering using the "table_info" method for this, but
> there's a problem there; I don't know how to ask DBI what database/catalog
> name I am currently working in, and "undef" is documented as returning
> tables in *every* database, not just the current one.
This is something I've been meaning to address for a while. I was
thinking of something like:
$schema_name = $dbh->current_schema
> So what I've done instead is defaulted to this query to check for a
> table:
>
> SELECT 1 FROM information_schema.tables WHERE table_name = ?
>
> ... then for MySQL,
>
> SHOW TABLES LIKE ?
>
> ... and SQLite2,
>
> SELECT 1 FROM sqlite_master WHERE type ='table' AND name = ?
>
> The default query does work for postgres, and I'm told I can expect
> it to work with M$SQL, Sybase, and Oracle as well. Can you think of any DBI
> drivers I should expect it to *not* work with?
Very few databases support information_schema.
The generic portable fallback is "select 1 from $table where 1=0" - if that
statement can be executed without error then the table exists.
> DB::Introspector claims to help you do this, so I might just use it.
> Although it does a lot more stuff that I don't need, and I only see MySQL,
> Oracle, and Postgres subclasses for it. Is there a better module or method
> out there?
I don't know off-hand.
Why not help save the world and help me add current_schema() to the DBI
and send implementations to the authors of drivers you're using?
Tim.