Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bulk Insert support? #61

Open
KnowZero opened this issue Aug 30, 2019 · 6 comments
Open

Bulk Insert support? #61

KnowZero opened this issue Aug 30, 2019 · 6 comments

Comments

@KnowZero
Copy link

KnowZero commented Aug 30, 2019

It would be nice to support multiple inserts in a single statement, especially non-blocking.

Maybe something like this?

my @values = [ [ 'cat', 1 ], [ 'dog', 2 ] ];
 $abstract->insert( 'pets' => {  -values=>\@values }  );

my @keys = [ 'name', 'rank' ];
 $abstract->insert( 'pets' => { -keys=> \@keys,  -values=>\@values }  );

my @keyvalues = [ { name=>'cat', rank=>1 }, { name=>'dog', rank=>2 }  ];
 $abstract->insert( 'pets' => {  -keyvalues=>\@keyvalues }  );

Then backend something like this?

sub _insert_HASHREF { 
  my ($self, $data) = @_;

if ( ref $$data{'-keyvalues'} eq 'ARRAY' ) {
$$data{'-keys'}=[ sort keys %{ $$data{'-keyvalues'}[0] } ];
$$data{'-values'} = [ map {   
    my $keyvalues=$_;
    [ map {  $$keyvalues{ $_ }  } @{ $$data{'-keys'} }  ]   
    } @{ $$data{'-keyvalues'} } ];
}
   
   return $self->SUPER::_insert_HASHREF($data) if ref $$data{'-values'} ne 'ARRAY';
 


my @fields = @{$$data{'-keys'}};
 

   my ( @all_bind, @all_values);
  foreach my $rec (@{ $$data{'-values'} }) { 
      my @values;
    foreach my $value (@$rec) {

      my ($values, @bind) = $self->_insert_value(undef, $value);
      push @values, $values;
      push @all_bind, @bind;
    }

    push @all_values, \@values;
  }
  my $sql = ( exists $$data{'-keys'} ? "( ".join(", ", @fields )." ) ":'' ).
              $self->_sqlcase('values').
              join(',', map{ " ( ".join(", ", @$_)." )" } @all_values  );

  return ($sql, @all_bind);

}

@kraih
Copy link
Member

kraih commented Dec 21, 2019

Yes, i would like to see bulk inserts too. But getting the code right is not so easy.

@KnowZero
Copy link
Author

Is there a problem with my approach of overwriting _insert_HASHREF?

or is it better to make a seperate bulk_insert function maybe?

@mrdvt92
Copy link

mrdvt92 commented Apr 4, 2022

I added bulk insert support to DBIx::Array you are more than welcome to see how that was implemented. https://metacpan.org/pod/DBIx::Array#METHODS-(Write)-Bulk-SQL

@marghidanu
Copy link

This would be a nice thing to have.

@kraih
Copy link
Member

kraih commented Jul 21, 2022

Note that SQL::Abstract::Pg is now a separate project. https://github.com/mojolicious/sql-abstract-pg

@marghidanu
Copy link

marghidanu commented Jul 21, 2022

I found a workaround! Since SQL::Abstract::Pg is a subclass of SQL::Abstract, all the plugins for SQL::Abstract will work directly. I stumbled upon SQL::Abstract::Plugin::InsertMulti and made a simple test:

package My::Model {
    use Mojo::Base -base, -signatures;

    use SQL::Abstract::Plugin::InsertMulti;

    has 'pg';

    sub insert_multi_p ( $self, $table, $data, $opts = {} ) {
        my ( $stmt, @bind ) =
          $self->pg()->abstract()->insert_multi( $table, $data, $opts );

        return $self->pg()->db()->query_p( $stmt, @bind );
    }
};

1;

So far, it works well. I hope it solves the problem for everyone else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants