X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=d6c637010922c64a15c64b153f836753e2bf3c8e;hb=aed5b8a46a2e48adeeb790c06906c4d48f190043;hp=dbddab3dd2f8a2bc9d0c25a4eb18c859a01334ef;hpb=14ad95291d2a5fe439fdb19058f05a685bd0331e;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index dbddab3..d6c6370 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -19,6 +19,9 @@ __PACKAGE__->mk_group_accessors('simple' => __PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor'); +__PACKAGE__->mk_group_accessors('inherited' => qw/sql_maker_class/); +__PACKAGE__->sql_maker_class('DBIC::SQL::Abstract'); + BEGIN { package DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :( @@ -83,6 +86,15 @@ sub select { my ($sql, @ret) = $self->SUPER::select( $table, $self->_recurse_fields($fields), $where, $order, @rest ); + $sql .= + $self->{for} ? + ( + $self->{for} eq 'update' ? ' FOR UPDATE' : + $self->{for} eq 'shared' ? ' FOR SHARE' : + '' + ) : + '' + ; return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql; } @@ -706,7 +718,7 @@ sub connected { sub _verify_pid { my ($self) = @_; - return if $self->_conn_pid == $$; + return if defined $self->_conn_pid && $self->_conn_pid == $$; $self->_dbh->{InactiveDestroy} = 1; $self->_dbh(undef); @@ -745,7 +757,8 @@ sub _sql_maker_args { sub sql_maker { my ($self) = @_; unless ($self->_sql_maker) { - $self->_sql_maker(new DBIC::SQL::Abstract( $self->_sql_maker_args )); + my $sql_maker_class = $self->sql_maker_class; + $self->_sql_maker($sql_maker_class->new( $self->_sql_maker_args )); } return $self->_sql_maker; } @@ -1085,9 +1098,15 @@ sub delete { sub _select { my ($self, $ident, $select, $condition, $attrs) = @_; my $order = $attrs->{order_by}; + if (ref $condition eq 'SCALAR') { $order = $1 if $$condition =~ s/ORDER BY (.*)$//i; } + + my $for = delete $attrs->{for}; + my $sql_maker = $self->sql_maker; + local $sql_maker->{for} = $for; + if (exists $attrs->{group_by} || $attrs->{having}) { $order = { group_by => $attrs->{group_by}, @@ -1103,8 +1122,12 @@ sub _select { } else { $self->throw_exception("rows attribute must be positive if present") if (defined($attrs->{rows}) && !($attrs->{rows} > 0)); + + # MySQL actually recommends this approach. I cringe. + $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset}; push @args, $attrs->{rows}, $attrs->{offset}; } + return $self->_execute(@args); } @@ -1309,21 +1332,22 @@ sub create_ddl_dir $version ||= $schema->VERSION || '1.x'; $sqltargs = { ( add_drop_table => 1 ), %{$sqltargs || {}} }; - $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.08: '} + $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.09: '} . $self->_check_sqlt_message . q{'}) if !$self->_check_sqlt_version; my $sqlt = SQL::Translator->new({ -# debug => 1, add_drop_table => 1, }); + + $sqlt->parser('SQL::Translator::Parser::DBIx::Class'); + my $sqlt_schema = $sqlt->translate({ data => $schema }) or die $sqlt->error; + foreach my $db (@$databases) { $sqlt->reset(); - $sqlt->parser('SQL::Translator::Parser::DBIx::Class'); -# $sqlt->parser_args({'DBIx::Class' => $schema); $sqlt = $self->configure_sqlt($sqlt, $db); - $sqlt->data($schema); + $sqlt->{schema} = $sqlt_schema; $sqlt->producer($db); my $file; @@ -1358,43 +1382,48 @@ sub create_ddl_dir warn("No previous schema file found ($prefilename)"); next; } - #### We need to reparse the SQLite file we just wrote, so that - ## Diff doesnt get all confoosed, and Diff is *very* confused. - ## FIXME: rip Diff to pieces! -# my $target_schema = $sqlt->schema; -# unless ( $target_schema->name ) { -# $target_schema->name( $filename ); -# } - my @input; - push @input, {file => $prefilename, parser => $db}; - push @input, {file => $filename, parser => $db}; - my ( $source_schema, $source_db, $target_schema, $target_db ) = map { - my $file = $_->{'file'}; - my $parser = $_->{'parser'}; + my $difffile = $schema->ddl_filename($db, $dir, $version, $preversion); + print STDERR "Diff: $difffile: $db, $dir, $version, $preversion \n"; + if(-e $difffile) + { + warn("$difffile already exists, skipping"); + next; + } + + my $source_schema; + { my $t = SQL::Translator->new; $t->debug( 0 ); $t->trace( 0 ); - $t->parser( $parser ) or die $t->error; - my $out = $t->translate( $file ) or die $t->error; - my $schema = $t->schema; - unless ( $schema->name ) { - $schema->name( $file ); + $t->parser( $db ) or die $t->error; + my $out = $t->translate( $prefilename ) or die $t->error; + $source_schema = $t->schema; + unless ( $source_schema->name ) { + $source_schema->name( $prefilename ); } - ($schema, $parser); - } @input; + } + + # The "new" style of producers have sane normalization and can support + # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't + # And we have to diff parsed SQL against parsed SQL. + my $dest_schema = $sqlt_schema; + + unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) { + my $t = SQL::Translator->new; + $t->debug( 0 ); + $t->trace( 0 ); + $t->parser( $db ) or die $t->error; + my $out = $t->translate( $filename ) or die $t->error; + $dest_schema = $t->schema; + $dest_schema->name( $filename ) + unless $dest_schema->name; + } my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db, - $target_schema, $db, + $dest_schema, $db, {} ); - my $difffile = $schema->ddl_filename($db, $dir, $version, $preversion); - print STDERR "Diff: $difffile: $db, $dir, $version, $preversion \n"; - if(-e $difffile) - { - warn("$difffile already exists, skipping"); - next; - } if(!open $file, ">$difffile") { $self->throw_exception("Can't write to $difffile ($!)"); @@ -1458,7 +1487,7 @@ sub deployment_statements { return join('', @rows); } - $self->throw_exception(q{Can't deploy without SQL::Translator 0.08: '} + $self->throw_exception(q{Can't deploy without SQL::Translator 0.09: '} . $self->_check_sqlt_message . q{'}) if !$self->_check_sqlt_version; @@ -1543,9 +1572,9 @@ sub build_datetime_parser { my $_check_sqlt_message; # private sub _check_sqlt_version { return $_check_sqlt_version if defined $_check_sqlt_version; - eval 'use SQL::Translator 0.08'; - $_check_sqlt_message = $@ ? $@ : ''; - $_check_sqlt_version = $@ ? 0 : 1; + eval 'use SQL::Translator "0.09"'; + $_check_sqlt_message = $@ || ''; + $_check_sqlt_version = !$@; } sub _check_sqlt_message {