Note: the incorrect implementation is not the fault of the original submitter
(who can not be expected to know the vagaries of the execution path) nor is
the fault of the original reviewer (who can not be expected to remember said
vagaries for a storage they do not even use). I do not have recommendations
on how to avoid this situation in the future.
It is correct that the particular problem can not be solved on the level of
SQLMaker::Oracle like it was solved for MySQL. However the current fix applies
the default-on-empty way too early in the call stack - there is a lot of stuff
happening between where we would ideally be applying the workaround and the
current application site. With an Oracle storage the call-stack is roughly the
following:
( ... non-storage code )
-> ::Storage::DBI::insert
X -> ::Storage::DBI::_prefetch_autovalues
X -> (loop over) ::Storage::DBI::Oracle::Generic::_sequence_fetch
X -> determine if autoincs are accounted for
? -> assemble INSERT RETURNING container
-> ::Storage::DBI::_execute
-> ::Storage::DBI::Oracle::Generic::_prep_for_execute
-> ::Storage::DBI::_prep_for_execute
-> ::Storage::DBI::_gen_sql_bind
-> ::SQLMaker::Oracle::insert(...)
Setting up the "missing" default so early definitely affects the points marked
with X and possibly affects the code marked with ?. The issues that would come
out of this range from obvious failure modes to "this will be easily broken by
a future reshuffle" gut feeling.
The patch therefore needs reworking adding the extra pieces of logic either in
a new _gen_sql_bind hook, or at the very least in the already existing
conditional at the start of ::Storage::DBI::Oracle::Generic::_prep_for_execute
(though a hook of _gen_sql_bind is preferable).
Additionally the test needs to be expanded to exercise the case of pre-existing
test cases that trigger _prefetch_autovalue (the tests involving the source
SequenceTest in t/73oracle.t)
And lastly an explicit exception should be added to SQLMaker::Oracle::insert
to catch future changes to any code higher up, so that a refactor will not
silently end up calling SQLMaker::Oracle::insert with an empty insert-list,
throwing everything back to square one.
This commit reverts the following two patches, with the intention to merge a
fixed-up version shortly:
-
236b59c8
-
1af6b968
kaare: Kaare Rasmussen
kd: Kieren Diment <diment@gmail.com>
konobi: Scott McWhirter <konobi@cpan.org>
-Lasse Makholm <lasse@unity3d.com>
lejeunerenard: Sean Zellmer <sean@lejeunerenard.com>
littlesavage: Alexey Illarionov <littlesavage@orionet.ru>
lukes: Luke Saunders <luke.saunders@gmail.com>
Revision history for DBIx::Class
* Fixes
- - Fix $rs->create() with no values on Oracle
- Silence with_deferred_fk_checks() warning on PostgreSQL 9.4
* Misc
$self->next::method($schema, $type, $version, $dir, $sqltargs, @rest);
}
-sub insert {
- my ($self, $source, $to_insert) = @_;
-
- # Oracle does not understand INSERT INTO ... DEFAULT VALUES syntax
- # Furthermore it does not have any way to insert without specifying any columns
- # We can't fix this in SQLMaker::Oracle because it doesn't know which column to add to the statement
- unless (%$to_insert)
- {
- my ($col) = $source->columns;
- $to_insert = { $col => \'DEFAULT' };
- }
-
- return $self->next::method($source, $to_insert);
-}
-
sub _dbh_last_insert_id {
my ($self, $dbh, $source, @columns) = @_;
my @ids = ();
{
my $new_artist = $schema->resultset('Artist')->new({});
isa_ok( $new_artist, 'DBIx::Class::Row', '$rs->new gives a row object' );
- lives_ok { $new_artist->insert() } 'inserting without specifying any columns works';
- $new_artist->discard_changes;
- $new_artist->delete;
}
# make sure we got rid of the compat shims
like ($seq, qr/\.${q}artist_pk_seq${q}$/, 'Correct PK sequence selected for sqlt-like trigger');
}
- lives_ok {
- $new = $schema->resultset('Artist')->create({});
- $new->discard_changes;
- ok $new->artistid, 'Created row has id'
- } 'Create with empty hashref works';
-
-
# test LIMIT support
for (1..6) {
$schema->resultset('Artist')->create({ name => 'Artist ' . $_ });