PApp
view release on metacpan or search on metacpan
PApp/DataRef.pm view on Meta::CPAN
sub STORE {
my $self = shift; my ($field, %args) = ref $_[0] ? @{+shift} : shift;
my @value = ref $args{store} ? $args{store}->($self, shift) : shift;
return unless @value;
Convert::Scalar::utf8_upgrade $value[0] if $self->{utf8} && (!ref $self->{utf8} || $self->{utf8}{$field});
if ($self->{delay}) {
$self->{_store}{$field} = \($self->{_cache}{$field} = $value[0]);
} else {
$self->{_cache}{$field} = $value[0] if $self->{cache};
$self->_sequence unless defined $self->{id};
sql_exec $self->dbh,
"update $self->{table} set $field = ? where $self->{key_expr}",
$value[0], @{$self->{id}};
$sql_exec > 0
or sql_exec $self->dbh,
"insert into $self->{table} (" .
(join ",", $field, @{$self->{key}}) .
") values (" .
(join ",", ("?") x (1 + @{$self->{key}})) .
")",
$value[0],
@{$self->{id}};
}
}
# we do not officially support iterators yet, but define them so we can display this object
sub FIRSTKEY {
my $self = shift;
keys %{$self->{_cache}};
each %{$self->{_cache}};
}
sub NEXTKEY {
my $self = shift;
each %{$self->{_cache}};
}
sub EXISTS {
my $self = shift;
my $field = shift;
exists $self->{_cache}{$field} or do {
# do it the slow way. not sure wether the limit 0 is portable or not
my $st = sql_exec $self->{database}->dbh,
"select * from $self->{table} limit 0";
my %f; @f{@{$st->{NAME_lc}}} = ();
$st->finish;
exists $f{lc $field};
};
}
=item @key = $hd->id
Returns the key value(s) for the selected row, creating it if necessary.
=cut
sub id($) {
my $self = shift;
$self->_sequence;
wantarray ? @{$self->{id}} : $self->{id}[0];
}
=item $hd->flush
Flush all pending store operations. See HOW FLUSHES ARE IMPLEMENTED below
to see how, well, flushes are implemented on the SQL-level.
=cut
sub flush {
my $self = shift;
my $store = delete $self->{_store};
if (%$store) {
my $dbh = $self->dbh;
my $insrep = sub {
sql_exec $dbh,
"$_[0] into $self->{table} (" .
(join ",", @{$self->{key}}, keys %$store) .
") values (" .
(join ",", ("?") x (@{$self->{key}} + keys %$store)) .
")",
@{$self->{id}},
(map $$_, values %$store);
};
my $update = sub {
sql_exec $dbh,
"update $self->{table} set" .
(join ",", map " $_ = ?", keys %$store) .
" where $self->{key_expr}",
(map $$_, values %$store), @{$self->{id}};
};
$self->_sequence unless $self->{id};
if (0 && $self->{preload} && !ref $self->{preload}
&& $dbh->{Driver}{Name} eq "mysql"
) {
# disabled because $store doesn't contain all values, and _cache might contain
# the id field twice. reenable when id is a normal member of _cache
$insrep->("replace");
delete $self->{preload}; # preload also acts as a "we know all columns" flag
} else {
&$update;
$sql_exec > 0 or eval { local $SIG{__DIE__}; $insrep->("insert") };
$sql_exec > 0 or &$update;
}
}
}
=item $hd->dirty
Return true when there are store operations that are delayed. Call
C<flush> to execute these.
( run in 0.489 second using v1.01-cache-2.11-cpan-524268b4103 )