[Dbix-class] Getting INSERT INTO ... SELECT support in DBIx::Class
Jose Luis Martinez
jlmartinez-lists-dbix at capside.com
Wed Jan 27 14:56:32 GMT 2010
Hi!
Recently we migrated a project from DBI raw prepare() and execute()
to DBIC, and had to do some "naughty stuff" to retain compatibility, but
now that release time is not pressing I'd like to clean it up, put
things in the right places, and contribute new functionalities back to DBIC.
One of the naughty bits that the app did, and that I had to work
around without DBIC was INSERT INTO table (...) [SELECT STATEMENT].
I already have a first approach, but I need some guidance to fit
the right bits into the right places, and see how to fit this into the
DBIC API correctly.
The final objective is to add a behaviour to the insert (maybe this
isn't the right spot) method so that you can then call
$table->insert($rs) on it, and you get an INSERT INTO table_name
(table_columns) SELECT SELECT_GENERATED_BY_$rs. This is lots faster that
looping over $rs, and inserting rows one by one.
The (working) proof of concept code that I have is:
# $options is a hashref that can be passed:
# - ignore => 1 to generate a INSERT IGNORE INTO statement.
# - mapping => [] array ref of column names to insert into.
# defaults to all columns of the table
sub insert_poc {
my ($self, $rs, $options) = @_;
# Get the SQL for the RS we are inserting. Is this sane?
my ($sql, @params) = @{ ${$rs->as_query()} };
# Ignore option
my $ignore = ($options->{ignore}==1)?'IGNORE':'';
my $mapping;
if (ref($options->{mapping}) eq 'ARRAY'){
$mapping = [ @{$options->{mapping}} ];
} else {
$mapping = [ $self->result_source->columns() ];
}
my $fields = join ',', @$mapping;
my $table = $self->result_source->from;
my $isql = "INSERT $ignore INTO $table ($fields) " . $sql;
my $dbh = $self->result_source->schema->storage->dbh();
my $sth = $dbh->prepare($isql);
# maybe this is even insaner...
$sth->execute(map { $_->[1] } @params);
$sth->finish;
}
But to get this up to standards, I would need some community review
/ thoughts, and some guidance as to put what where. (Patch
SQL::Abstract? Is the insert method the right / expected place to put
this functionality? More use cases?)
Thanks in advance,
Jose Luis Martinez
jlmartinez at capside.com
More information about the DBIx-Class
mailing list