use Try::Tiny;
use overload ();
use Data::Compare (); # no imports!!! guard against insane architecture
-use DBI::Const::GetInfoType (); # no import of retarded global hash
use namespace::clean;
# default cursor class, overridable in connect_info attributes
# _determine_supports_X which obv. needs a correct driver as well
my @rdbms_specific_methods = qw/
sqlt_type
+ deployment_statements
+
sql_maker
+ cursor_class
+
build_datetime_parser
datetime_parser_type
txn_begin
+
insert
insert_bulk
update
delete
select
select_single
+
with_deferred_fk_checks
get_use_dbms_capability
# would e.g. be setting a default for an inherited accessor
ref $_[0]
and
- ! $_[0]->_driver_determined
+ ! $_[0]->{_driver_determined}
and
! $_[0]->{_in_determine_driver}
+ and
+ ($_[0]->_dbi_connect_info||[])->[0]
) {
$_[0]->_determine_driver;
my @args = @{ $info->{arguments} };
if (keys %attrs and ref $args[0] ne 'CODE') {
- carp
+ carp_unique (
'You provided explicit AutoCommit => 0 in your connection_info. '
. 'This is almost universally a bad idea (see the footnotes of '
. 'DBIx::Class::Storage::DBI for more info). If you still want to '
. 'do this you can set $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK} to disable '
. 'this warning.'
- if ! $attrs{AutoCommit} and ! $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK};
+ ) if ! $attrs{AutoCommit} and ! $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK};
push @args, \%attrs if keys %attrs;
}
# short circuit when we know there is no need for a runner
#
- # FIXME - asumption may be wrong
+ # FIXME - assumption may be wrong
# the rationale for the txn_depth check is that if this block is a part
# of a larger transaction, everything up to that point is screwed anyway
return $self->$run_target($self->_get_dbh, @_)
||
do {
my $s_class = (ref $self) || $self;
- carp (
+ carp_unique (
"Your storage class ($s_class) does not set sql_limit_dialect and you "
. 'have not supplied an explicit limit_dialect in your connection_info. '
. 'DBIC will attempt to use the GenericSubQ dialect, which works on most '
. 'databases but can be (and often is) painfully slow. '
- . "Please file an RT ticket against '$s_class' ."
- );
+ . "Please file an RT ticket against '$s_class'"
+ ) if $self->_dbi_connect_info->[0];
'GenericSubQ';
}
if ($opts{quote_names}) {
$quote_char = (delete $opts{quote_char}) || $self->sql_quote_char || do {
my $s_class = (ref $self) || $self;
- carp (
+ carp_unique (
"You requested 'quote_names' but your storage class ($s_class) does "
. 'not explicitly define a default sql_quote_char and you have not '
. 'supplied a quote_char as part of your connection_info. DBIC will '
my ($self, $info) = @_;
if ($info =~ /[^0-9]/) {
+ require DBI::Const::GetInfoType;
$info = $DBI::Const::GetInfoType::GetInfoType{$info};
$self->throw_exception("Info type '$_[1]' not provided by DBI::Const::GetInfoType")
unless defined $info;
}
- return $self->_get_dbh->get_info($info);
+ $self->_get_dbh->get_info($info);
}
sub _describe_connection {
sub _connect {
my ($self, @info) = @_;
- $self->throw_exception("You failed to provide any connection info")
- if !@info;
+ $self->throw_exception("You did not provide any connection_info")
+ if ( ! defined $info[0] and ! $ENV{DBI_DSN} and ! $ENV{DBI_DRIVER} );
my ($old_connect_via, $dbh);
$colinfos = $ident->columns_info;
}
- my ($sql, @bind) = $self->sql_maker->$op( ($from || $ident), @$args );
+ my ($sql, $bind);
+ ($sql, @$bind) = $self->sql_maker->$op( ($from || $ident), @$args );
+
+ $bind = $self->_resolve_bindattrs(
+ $ident, [ @{$args->[2]{bind}||[]}, @$bind ], $colinfos
+ );
if (
! $ENV{DBIC_DT_SEARCH_OK}
and
$op eq 'select'
and
- first { blessed($_->[1]) && $_->[1]->isa('DateTime') } @bind
+ first {
+ length ref $_->[1]
+ and
+ blessed($_->[1])
+ and
+ $_->[1]->isa('DateTime')
+ } @$bind
) {
carp_unique 'DateTime objects passed to search() are not supported '
. 'properly (InflateColumn::DateTime formats and settings are not '
. 'set $ENV{DBIC_DT_SEARCH_OK} to true'
}
- return( $sql, $self->_resolve_bindattrs(
- $ident, [ @{$args->[2]{bind}||[]}, @bind ], $colinfos
- ));
+ return( $sql, $bind );
}
sub _resolve_bindattrs {
};
return [ map {
- if (ref $_ ne 'ARRAY') {
- [{}, $_]
- }
- elsif (! defined $_->[0]) {
- [{}, $_->[1]]
- }
- elsif (ref $_->[0] eq 'HASH') {
- [
- ($_->[0]{dbd_attrs} or $_->[0]{sqlt_datatype}) ? $_->[0] : $resolve_bindinfo->($_->[0]),
- $_->[1]
- ]
- }
- elsif (ref $_->[0] eq 'SCALAR') {
- [ { sqlt_datatype => ${$_->[0]} }, $_->[1] ]
- }
- else {
- [ $resolve_bindinfo->({ dbic_colname => $_->[0] }), $_->[1] ]
+ my $resolved =
+ ( ref $_ ne 'ARRAY' or @$_ != 2 ) ? [ {}, $_ ]
+ : ( ! defined $_->[0] ) ? [ {}, $_->[1] ]
+ : (ref $_->[0] eq 'HASH') ? [ (exists $_->[0]{dbd_attrs} or $_->[0]{sqlt_datatype})
+ ? $_->[0]
+ : $resolve_bindinfo->($_->[0])
+ , $_->[1] ]
+ : (ref $_->[0] eq 'SCALAR') ? [ { sqlt_datatype => ${$_->[0]} }, $_->[1] ]
+ : [ $resolve_bindinfo->(
+ { dbic_colname => $_->[0] }
+ ), $_->[1] ]
+ ;
+
+ if (
+ ! exists $resolved->[0]{dbd_attrs}
+ and
+ ! $resolved->[0]{sqlt_datatype}
+ and
+ length ref $resolved->[1]
+ and
+ ! overload::Method($resolved->[1], '""')
+ ) {
+ require Data::Dumper;
+ local $Data::Dumper::Maxdepth = 1;
+ local $Data::Dumper::Terse = 1;
+ local $Data::Dumper::Useqq = 1;
+ local $Data::Dumper::Indent = 0;
+ local $Data::Dumper::Pad = ' ';
+ $self->throw_exception(
+ 'You must supply a datatype/bindtype (see DBIx::Class::ResultSet/DBIC BIND VALUES) '
+ . 'for non-scalar value '. Data::Dumper::Dumper ($resolved->[1])
+ );
}
+
+ $resolved;
+
} @$bind ];
}
}
sub _select_args {
- my ($self, $ident, $select, $where, $attrs) = @_;
+ my ($self, $ident, $select, $where, $orig_attrs) = @_;
+
+ # FIXME - that kind of caching would be nice to have
+ # however currently we *may* pass the same $orig_attrs
+ # with different ident/select/where
+ # the whole interface needs to be rethought, since it
+ # was centered around the flawed SQLA API. We can do
+ # soooooo much better now. But that is also another
+ # battle...
+ #return (
+ # 'select', @{$orig_attrs->{_sqlmaker_select_args}}
+ #) if $orig_attrs->{_sqlmaker_select_args};
my $sql_maker = $self->sql_maker;
my $alias2source = $self->_resolve_ident_sources ($ident);
- $attrs = {
- %$attrs,
+ my $attrs = {
+ %$orig_attrs,
select => $select,
from => $ident,
where => $where,
# limit dialects use this stuff
# yes, some CDBICompat crap does not supply an {alias} >.<
- ( $attrs->{alias} and $alias2source->{$attrs->{alias}} )
- ? ( _rsroot_rsrc => $alias2source->{$attrs->{alias}} )
+ ( $orig_attrs->{alias} and $alias2source->{$orig_attrs->{alias}} )
+ ? ( _rsroot_rsrc => $alias2source->{$orig_attrs->{alias}} )
: ()
,
};
and
@$ident != 1
) {
- ($ident) = $self->_prune_unused_joins ($ident, $select, $where, $attrs);
+ ($ident, $attrs->{_aliastypes}) = $self->_prune_unused_joins ($ident, $select, $where, $attrs);
}
###
# invoked, and that's just bad...
###
- return ('select', $ident, $select, $where, $attrs, @limit_args);
+ return ( 'select', @{ $orig_attrs->{_sqlmaker_select_args} = [
+ $ident, $select, $where, $attrs, @limit_args
+ ]} );
}
# Returns a counting SELECT for a simple count
$self->throw_exception("Can't deploy without a ddl_dir or " . DBIx::Class::Optional::Dependencies->req_missing_for ('deploy') );
}
- # sources needs to be a parser arg, but for simplicty allow at top level
+ # sources needs to be a parser arg, but for simplicity allow at top level
# coming in
$sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
if exists $sqltargs->{sources};