- Fixed ::Schema::Versioned to work properly with quoting on
(RT#59619)
- Fixed t/54taint fails under local-lib
+ - Fixed SELECT ... FOR UPDATE with LIMIT regression (RT#58554)
* Misc
- Refactored capability handling in Storage::DBI, allows for
# this *must* be called, otherwise extra binds will remain in the sql-maker
my @all_bind = $self->_assemble_binds;
+ $sql .= $self->_lock_select ($rs_attrs->{for})
+ if $rs_attrs->{for};
+
return wantarray ? ($sql, @all_bind) : $sql;
}
return map { @{ (delete $self->{"${_}_bind"}) || [] } } (qw/from where having order/);
}
+my $for_syntax = {
+ update => 'FOR UPDATE',
+ shared => 'FOR SHARE',
+};
+sub _lock_select {
+ my ($self, $type) = @_;
+ my $sql = $for_syntax->{$type} || croak "Unknown SELECT .. FOR type '$type' requested";
+ return " $sql";
+}
+
# Handle default inserts
sub insert {
# optimized due to hotttnesss
}
}
-my $for_syntax = {
- update => 'FOR UPDATE',
- shared => 'FOR SHARE',
-};
# this used to be a part of _order_by but is broken out for clarity.
# What we have been doing forever is hijacking the $order arg of
$sql .= $self->_order_by ($arg->{order_by});
}
- if (my $for = $arg->{for}) {
- $sql .= " $for_syntax->{$for}" if $for_syntax->{$for};
- }
-
return $sql;
}
# also return a hashref (order doesn't matter) of QUOTED EXTRA-SEL =>
# QUOTED ALIAS pairs, which is a list of extra selectors that do *not*
# exist in the original select list
-
sub _subqueried_limit_attrs {
my ($self, $rs_attrs) = @_;
my $sql_sel = $self->_recurse_fields ($s);
my $sql_alias = (ref $s) eq 'HASH' ? $s->{-as} : undef;
-
push @sel, {
sql => $sql_sel,
unquoted_sql => do { local $self->{quote_char}; $self->_recurse_fields ($s) },
#
# SQLite does not understand SELECT ... FOR UPDATE
# Disable it here
-#
-sub _parse_rs_attrs {
- my ($self, $attrs) = @_;
-
- return $self->SUPER::_parse_rs_attrs ($attrs)
- if ref $attrs ne 'HASH';
-
- local $attrs->{for};
- return $self->SUPER::_parse_rs_attrs ($attrs);
-}
+sub _lock_select { '' };
1;
$it->next;
is( $it->next, undef, "next past end of resultset ok" );
+# Limit with select-lock
+lives_ok {
+ $schema->txn_do (sub {
+ isa_ok (
+ $schema->resultset('Artist')->find({artistid => 1}, {for => 'update', rows => 1}),
+ 'DBICTest::Schema::Artist',
+ );
+ });
+} 'Limited FOR UPDATE select works';
+
my $test_type_info = {
'artistid' => {
'data_type' => 'INT',
$it->next;
$it->next;
is( $it->next, undef, "next past end of resultset ok" );
+
+ # Limit with select-lock
+ lives_ok {
+ $schema->txn_do (sub {
+ isa_ok (
+ $schema->resultset('Artist')->find({artistid => 1}, {for => 'update', rows => 1}),
+ 'DBICTest::Schema::Artist',
+ );
+ });
+ } 'Limited FOR UPDATE select works';
}
# check if we indeed do support stuff
is( $lim->count, 2, 'ROWS+OFFSET count ok' );
is( $lim->all, 2, 'Number of ->all objects matches count' );
+# Limit with select-lock
+TODO: {
+ local $TODO = "Seems we can't SELECT ... FOR ... on subqueries";
+ lives_ok {
+ $schema->txn_do (sub {
+ isa_ok (
+ $schema->resultset('Artist')->find({artistid => 1}, {for => 'update', rows => 1}),
+ 'DBICTest::Schema::Artist',
+ );
+ });
+ } 'Limited FOR UPDATE select works';
+}
+
# test iterator
$lim->reset;
is( $lim->next->artistid, 101, "iterator->next ok" );