die "Virtual method!";
}
+sub all {
+ my ($self) = @_;
+ $self->reset;
+ my @all;
+ while (my @row = $self->next) {
+ push(@all, \@row);
+ }
+ $self->reset;
+ return @all;
+}
+
1;
if (ref $vals[0] eq 'HASH') {
$query = $vals[0];
} elsif (@pk == @vals) {
- my $ret = ($class->search_literal($class->_ident_cond, @vals, $attrs))[0];
+ $query = {};
+ @{$query}{@pk} = @vals;
+ #my $ret = ($class->search_literal($class->_ident_cond, @vals, $attrs))[0];
#warn "$class: ".join(', ', %{$ret->{_column_data}});
- return $ret;
+ #return $ret;
} else {
$query = {@vals};
}
$class->throw( "Can't find unless all primary keys are specified" )
unless (keys %$query >= @pk); # If we check 'em we run afoul of uc/lc
# column names etc. Not sure what to do yet
- my $ret = ($class->search($query))[0];
- #warn "$class: ".join(', ', %{$ret->{_column_data}});
- return $ret;
+ #return $class->search($query)->next;
+ my @cols = $class->_select_columns;
+ my @row = $class->storage->select_single($class->_table_name, \@cols, $query);
+ return (@row ? $class->_row_to_object(\@cols, \@row) : ());
}
sub discard_changes {
} elsif (exists $self->{_relationship_data}{$rel}) {
return $self->{_relationship_data}{$rel};
} else {
- my ($val) = $self->search_related($rel, {}, {});
+ my $val = $self->find_related($rel, {}, {});
return unless $val;
return $self->{_relationship_data}{$rel} = $val;
}
return $self->resolve_class($rel_obj->{class})->new(\%fields);
}
+sub find_related {
+ my $self = shift;
+ my $rel = shift;
+ my $rel_obj = $self->_relationships->{$rel};
+ $self->throw( "No such relationship ${rel}" ) unless $rel_obj;
+ my ($cond) = $self->resolve_condition($rel_obj->{cond}, { _action => 'convert' });
+ $self->throw( "Invalid query: @_" ) if (@_ > 1 && (@_ % 2 == 1));
+ my $attrs = { };
+ if (@_ > 1 && ref $_[$#_] eq 'HASH') {
+ $attrs = { %{ pop(@_) } };
+ }
+ my $query = ((@_ > 1) ? {@_} : shift);
+ $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
+ return $self->resolve_class($rel_obj->{class})->find($query);
+}
+
sub find_or_create_related {
my $self = shift;
- return ($self->search_related(@_))[0] || $self->create_related(@_);
+ return $self->find_related(@_) || $self->create_related(@_);
}
sub set_from_related {
my $db_class = $self->{class};
my @cols = 'COUNT(*)';
- my $cursor = $db_class->storage->select($db_class->_table_name, \@cols,
+ my ($c) = $db_class->storage->select_single($db_class->_table_name, \@cols,
$self->{cond}, $self->{attrs});
- return ($cursor->next)[0];
+ return $c; # ($cursor->next)[0];
}
sub all {
my ($self) = @_;
- $self->reset;
- my @all;
- while (my $obj = $self->next) {
- push(@all, $obj);
- }
- $self->reset;
- return @all;
+ return map { $self->{class}->_row_to_object($self->{cols}, $_); }
+ $self->{cursor}->all;
}
sub reset {
return $self->{_column_data}{$column} = $value;
}
-sub _row_to_object { # WARNING: Destructive to @$row
+sub _row_to_object {
my ($class, $cols, $row) = @_;
- my $new = $class->new;
- $new->store_column($_, shift @$row) for @$cols;
+ my %vals;
+ $vals{$cols->[$_]} = $row->[$_] for 0 .. $#$cols;
+ my $new = $class->new(\%vals);
$new->in_storage(1);
return $new;
}
return $self->cursor->new($sth, \@bind, $attrs);
}
+sub select_single {
+ 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 ($rv, $sth, @bind) = $self->_execute('select', $attrs->{bind}, $ident, $select, $condition, $order);
+ return $sth->fetchrow_array;
+}
+
sub sth {
shift->dbh->prepare(@_);
}
my ($self) = @_;
return if $self->{attrs}{rows}
&& $self->{pos} >= $self->{attrs}{rows}; # + $self->{attrs}{offset});
+ my $sth = $self->{sth};
unless ($self->{live_sth}) {
- $self->{sth}->execute(@{$self->{args} || []});
+ $sth->execute(@{$self->{args} || []});
if (my $offset = $self->{attrs}{offset}) {
- $self->{sth}->fetch for 1 .. $offset;
+ $sth->fetch for 1 .. $offset;
}
$self->{live_sth} = 1;
}
- my @row = $self->{sth}->fetchrow_array;
+ my @row = $sth->fetchrow_array;
$self->{pos}++ if @row;
return @row;
}
+sub all {
+ my ($self) = @_;
+ return $self->SUPER::all if $self->{attrs}{rows};
+ my $sth = $self->{sth};
+ $sth->finish if $sth->{Active};
+ $sth->execute(@{$self->{args} || []});
+ delete $self->{live_sth};
+ return @{$sth->fetchall_arrayref};
+}
+
sub reset {
my ($self) = @_;
$self->{sth}->finish if $self->{sth}->{Active};
sub find_or_create {
my $class = shift;
my $hash = ref $_[0] eq "HASH" ? shift: {@_};
- my ($exists) = $class->search($hash);
+ my $exists = $class->find($hash);
return defined($exists) ? $exists : $class->create($hash);
}