use DBI;
use DBIx::Class::Storage::DBI::Cursor;
use DBIx::Class::Storage::Statistics;
-use Scalar::Util qw/blessed weaken/;
+use Scalar::Util();
use List::Util();
__PACKAGE__->mk_group_accessors('simple' =>
if($dbh && !$self->unsafe) {
my $weak_self = $self;
- weaken($weak_self);
+ Scalar::Util::weaken($weak_self);
$dbh->{HandleError} = sub {
if ($weak_self) {
$weak_self->throw_exception("DBI Exception: $_[0]");
sub _prep_for_execute {
my ($self, $op, $extra_bind, $ident, $args) = @_;
- if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
+ if( Scalar::Util::blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
$ident = $ident->from();
}
return ($sql, \@bind);
}
+
sub _fix_bind_params {
my ($self, @bind) = @_;
my $self = shift @_;
my $source = shift @_;
- my $bind_attrs = {}; ## If ever it's needed...
+ my $bind_attrs = $self->source_bind_attributes($source);
return $self->_execute('delete' => [], $source, $bind_attrs, @_);
}
sub _select {
my $self = shift;
+
+ # localization is neccessary as
+ # 1) there is no infrastructure to pass this around before SQLA2
+ # 2) _select_args sets it and _prep_for_execute consumes it
my $sql_maker = $self->sql_maker;
- local $sql_maker->{for};
+ local $sql_maker->{_dbic_rs_attrs};
+
return $self->_execute($self->_select_args(@_));
}
+sub _select_args_to_query {
+ my $self = shift;
+
+ # localization is neccessary as
+ # 1) there is no infrastructure to pass this around before SQLA2
+ # 2) _select_args sets it and _prep_for_execute consumes it
+ my $sql_maker = $self->sql_maker;
+ local $sql_maker->{_dbic_rs_attrs};
+
+ # my ($op, $bind, $ident, $bind_attrs, $select, $cond, $order, $rows, $offset)
+ # = $self->_select_args($ident, $select, $cond, $attrs);
+ my ($op, $bind, $ident, $bind_attrs, @args) =
+ $self->_select_args(@_);
+
+ # my ($sql, $prepared_bind) = $self->_prep_for_execute($op, $bind, $ident, [ $select, $cond, $order, $rows, $offset ]);
+ my ($sql, $prepared_bind) = $self->_prep_for_execute($op, $bind, $ident, \@args);
+ $prepared_bind ||= [];
+
+ return wantarray
+ ? ($sql, $prepared_bind, $bind_attrs)
+ : \[ "($sql)", @$prepared_bind ]
+ ;
+}
+
sub _select_args {
my ($self, $ident, $select, $condition, $attrs) = @_;
- my $for = delete $attrs->{for};
my $sql_maker = $self->sql_maker;
- $sql_maker->{for} = $for;
+ $sql_maker->{_dbic_rs_attrs} = $attrs;
my $order = { map
{ $attrs->{$_} ? ( $_ => $attrs->{$_} ) : () }
(qw/order_by group_by having _virtual_order_by/ )
};
- my $bind_attrs = {}; ## Future support
+
+ my $bind_attrs = {};
+
+ my $alias2source = $self->_resolve_ident_sources ($ident);
+
+ for my $alias (keys %$alias2source) {
+ my $bindtypes = $self->source_bind_attributes ($alias2source->{$alias}) || {};
+ for my $col (keys %$bindtypes) {
+
+ my $fqcn = join ('.', $alias, $col);
+ $bind_attrs->{$fqcn} = $bindtypes->{$col} if $bindtypes->{$col};
+
+ # so that unqualified searches can be bound too
+ $bind_attrs->{$col} = $bind_attrs->{$fqcn} if $alias eq 'me';
+ }
+ }
+
+ # This would be the point to deflate anything found in $condition
+ # (and leave $attrs->{bind} intact). Problem is - inflators historically
+ # expect a row object. And all we have is a resultsource (it is trivial
+ # to extract deflator coderefs via $alias2source above).
+ #
+ # I don't see a way forward other than changing the way deflators are
+ # invoked, and that's just bad...
+
my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
if ($attrs->{software_limit} ||
$sql_maker->_default_limit_syntax eq "GenericSubQ") {
$tabinfo = $_->[0];
}
- $alias2source->{$tabinfo->{-alias}} = $tabinfo->{-result_source}
- if ($tabinfo->{-result_source});
+ $alias2source->{$tabinfo->{-alias}} = $tabinfo->{-source_handle}->resolve
+ if ($tabinfo->{-source_handle});
}
}
return $alias2source;
}
+# Takes $ident, \@column_names
+#
+# returns { $column_name => \%column_info, ... }
+# also note: this adds -result_source => $rsrc to the column info
+#
+# usage:
+# my $col_sources = $self->_resolve_column_info($ident, [map $_->[0], @{$bind}]);
+sub _resolve_column_info {
+ my ($self, $ident, $colnames) = @_;
+ my $alias2src = $self->_resolve_ident_sources($ident);
+
+ my $sep = $self->_sql_maker_opts->{name_sep} || '.';
+ $sep = "\Q$sep\E";
+
+ my %return;
+ foreach my $col (@{$colnames}) {
+ $col =~ m/^ (?: ([^$sep]+) $sep)? (.+) $/x;
+
+ my $alias = $1 || 'me';
+ my $colname = $2;
+
+ my $rsrc = $alias2src->{$alias};
+ $return{$col} = $rsrc && { %{$rsrc->column_info($colname)}, -result_source => $rsrc };
+ }
+ return \%return;
+}
+
sub count {
my ($self, $source, $attrs) = @_;
return;
}
+=head2 is_datatype_numeric
+
+Given a datatype from column_info, returns a boolean value indicating if
+the current RDBMS considers it a numeric value. This controls how
+L<DBIx::Class::Row/set_column> decides whether to mark the column as
+dirty - when the datatype is deemed numeric a C<< != >> comparison will
+be performed instead of the usual C<eq>.
+
+=cut
+
+sub is_datatype_numeric {
+ my ($self, $dt) = @_;
+
+ return 0 unless $dt;
+
+ return $dt =~ /^ (?:
+ numeric | int(?:eger)? | (?:tiny|small|medium|big)int | dec(?:imal)? | real | float | double (?: \s+ precision)? | (?:big)?serial
+ ) $/ix;
+}
+
+
=head2 create_ddl_dir (EXPERIMENTAL)
=over 4