[Bps-public-commit] dbix-searchbuilder branch, cud-from-select, created. 1.59-9-gbc97240

Ruslan Zakirov ruz at bestpractical.com
Sun Mar 27 19:37:32 EDT 2011


The branch, cud-from-select has been created
        at  bc9724006933fbc870dacefa9d37d6fd9a24b4e5 (commit)

- Log -----------------------------------------------------------------
commit c351dfc0cf7f4e0ee7c1129db12a078a7e2857fb
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Mar 26 04:20:46 2011 +0300

    SimpleUpdateFromSelect method in SB::Handle

diff --git a/lib/DBIx/SearchBuilder/Handle.pm b/lib/DBIx/SearchBuilder/Handle.pm
index 51f1e8d..0bb91aa 100755
--- a/lib/DBIx/SearchBuilder/Handle.pm
+++ b/lib/DBIx/SearchBuilder/Handle.pm
@@ -473,6 +473,35 @@ sub UpdateTableValue  {
     return $self->UpdateRecordValue(%args)
 }
 
+=head1 SimpleUpdateFromSelect
+
+Takes table name, hash reference with (column, value) pairs,
+select query and list of bind values.
+
+Updates the table, but only records with IDs returned by the
+selected query, eg:
+
+    UPDATE $table SET %values WHERE id IN ( $query )
+
+It's simple as values are static and search only allowed
+by id.
+
+=cut
+
+sub SimpleUpdateFromSelect {
+    my ($self, $table, $values, $query, @query_binds) = @_;
+
+    my @columns; my @binds;
+    while ( my ($k, $v) = each %$values ) {
+        push @columns, $k;
+        push @binds, $v;
+    }
+
+    my $full_query = "UPDATE $table SET ";
+    $full_query .= join ' AND ', map "$_ = ?", @columns;
+    $full_query .= ' WHERE id IN ('. $query .')';
+    return $self->SimpleQuery( $full_query, @binds );
+}
 
 =head2 SimpleQuery QUERY_STRING, [ BIND_VALUE, ... ]
 
diff --git a/lib/DBIx/SearchBuilder/Handle/mysql.pm b/lib/DBIx/SearchBuilder/Handle/mysql.pm
index efaac1a..4fd3240 100755
--- a/lib/DBIx/SearchBuilder/Handle/mysql.pm
+++ b/lib/DBIx/SearchBuilder/Handle/mysql.pm
@@ -50,6 +50,50 @@ sub Insert  {
   }
 
 
+=head2 SimpleUpdateFromSelect
+
+Customization of L<DBIx::SearchBuilder::Handle/SimpleUpdateFromSelect>.
+Mysql doesn't support update with subqueries when those fetch data from
+the table that is updated.
+
+=cut
+
+sub SimpleUpdateFromSelect {
+    my ($self, $table, $values, $query, @query_binds) = @_;
+
+    return $self->SUPER::SimpleUpdateFromSelect(
+        $table, $values, $query, @query_binds
+    ) unless $query =~ /\b\Q$table\E\b/i;
+
+    my $sth = $self->SimpleQuery( $query, @query_binds );
+    return $sth unless $sth;
+
+    my (@binds, @columns);
+    while ( my ($k, $v) = each %$values ) {
+        push @columns, $k;
+        push @binds, $v;
+    }
+
+    my $update_query = "UPDATE $table SET "
+        . join( ' AND ', map "$_ = ?", @columns )
+        .' WHERE ID IN ';
+
+    my @ids;
+    while ( my $id = ($sth->fetchrow_array)[0] ) {
+        push @ids, $id;
+        next if @ids < 100;
+
+        my $q = $update_query .'('. join( ',', ('?')x at ids ) .')';
+        my $sth = $self->SimpleQuery( $q, @binds, splice @ids );
+        return $sth unless $sth;
+    }
+    if ( @ids ) {
+        my $q = $update_query .'('. join( ',', ('?')x at ids ) .')';
+        my $sth = $self->SimpleQuery( $q, @binds, splice @ids );
+        return $sth unless $sth;
+    }
+    return 1;
+}
 
 =head2 DatabaseVersion
 

commit 3993ae988587e8733052944634a648e9bdb1275d
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Mar 28 03:25:06 2011 +0400

    DeleteFromSelect method

diff --git a/lib/DBIx/SearchBuilder/Handle.pm b/lib/DBIx/SearchBuilder/Handle.pm
index 0bb91aa..52f9427 100755
--- a/lib/DBIx/SearchBuilder/Handle.pm
+++ b/lib/DBIx/SearchBuilder/Handle.pm
@@ -503,6 +503,29 @@ sub SimpleUpdateFromSelect {
     return $self->SimpleQuery( $full_query, @binds );
 }
 
+=head1 DeleteFromSelect
+
+Takes table name, select query and list of bind values.
+
+Deletes from the table, but only records with IDs returned by the
+select query, eg:
+
+    DELETE FROM $table WHERE id IN ($query)
+
+=cut
+
+sub DeleteFromSelect {
+    my ($self, $table, $query, @binds) = @_;
+    my $sth = $self->SimpleQuery(
+        "DELETE FROM $table WHERE id IN ($query)",
+        @binds
+    );
+    return $sth unless $sth;
+
+    my $rows = $sth->rows;
+    return $rows == 0? '0E0' : $rows;
+}
+
 =head2 SimpleQuery QUERY_STRING, [ BIND_VALUE, ... ]
 
 Execute the SQL string specified in QUERY_STRING

commit ea17703152a118f0192dab94722196ece72adbef
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Mar 28 03:25:54 2011 +0400

    return number of affected rows from new *FromSelect methods

diff --git a/lib/DBIx/SearchBuilder/Handle.pm b/lib/DBIx/SearchBuilder/Handle.pm
index 52f9427..e53d10c 100755
--- a/lib/DBIx/SearchBuilder/Handle.pm
+++ b/lib/DBIx/SearchBuilder/Handle.pm
@@ -401,7 +401,11 @@ sub InsertFromSelect {
     my $full_query = "INSERT INTO $table";
     $full_query .= " ($columns)" if $columns;
     $full_query .= ' '. $query;
-    return $self->SimpleQuery( $full_query, @binds );
+    my $sth = $self->SimpleQuery( $full_query, @binds );
+    return $sth unless $sth;
+
+    my $rows = $sth->rows;
+    return $rows == 0? '0E0' : $rows;
 }
 
 =head2 UpdateRecordValue 
@@ -500,7 +504,11 @@ sub SimpleUpdateFromSelect {
     my $full_query = "UPDATE $table SET ";
     $full_query .= join ' AND ', map "$_ = ?", @columns;
     $full_query .= ' WHERE id IN ('. $query .')';
-    return $self->SimpleQuery( $full_query, @binds );
+    my $sth = $self->SimpleQuery( $full_query, @binds );
+    return $sth unless $sth;
+
+    my $rows = $sth->rows;
+    return $rows == 0? '0E0' : $rows;
 }
 
 =head1 DeleteFromSelect

commit d4bfb7ba7d7bb6598c8b0016331e6144efd2c85e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Mar 28 03:27:19 2011 +0400

    custom Delete and Update from select for mysql
    
    * use one generic method for both
    * process 1000 records at a time
    * return number of rows

diff --git a/lib/DBIx/SearchBuilder/Handle/mysql.pm b/lib/DBIx/SearchBuilder/Handle/mysql.pm
index 4fd3240..c300df2 100755
--- a/lib/DBIx/SearchBuilder/Handle/mysql.pm
+++ b/lib/DBIx/SearchBuilder/Handle/mysql.pm
@@ -78,21 +78,56 @@ sub SimpleUpdateFromSelect {
         . join( ' AND ', map "$_ = ?", @columns )
         .' WHERE ID IN ';
 
+    return $self->SimpleMassChangeFromSelect(
+        $update_query, \@binds,
+        $query, @query_binds
+    );
+}
+
+
+sub DeleteFromSelect {
+    my ($self, $table, $query, @query_binds) = @_;
+
+    return $self->SUPER::DeleteFromSelect(
+        $table, $query, @query_binds
+    ) unless $query =~ /\b\Q$table\E\b/i;
+
+    my $sth = $self->SimpleQuery( $query, @query_binds );
+    return $sth unless $sth;
+
+    return $self->SimpleMassChangeFromSelect(
+        "DELETE FROM $table WHERE id IN ", [],
+        $query, @query_binds
+    );
+}
+
+sub SimpleMassChangeFromSelect {
+    my ($self, $update_query, $update_binds, $search, @search_binds) = @_;
+
+    my $sth = $self->SimpleQuery( $search, @search_binds );
+    return $sth unless $sth;
+
+    my $res = 0;
+
     my @ids;
     while ( my $id = ($sth->fetchrow_array)[0] ) {
         push @ids, $id;
-        next if @ids < 100;
+        next if @ids < 1000;
 
         my $q = $update_query .'('. join( ',', ('?')x at ids ) .')';
-        my $sth = $self->SimpleQuery( $q, @binds, splice @ids );
+        my $sth = $self->SimpleQuery( $q, @$update_binds, splice @ids );
         return $sth unless $sth;
+
+        $res += @ids;
     }
     if ( @ids ) {
         my $q = $update_query .'('. join( ',', ('?')x at ids ) .')';
-        my $sth = $self->SimpleQuery( $q, @binds, splice @ids );
+        my $sth = $self->SimpleQuery( $q, @$update_binds, splice @ids );
         return $sth unless $sth;
+
+        $res += @ids;
     }
-    return 1;
+    return $res == 0? '0E0': $res;
 }
 
 =head2 DatabaseVersion

commit bc9724006933fbc870dacefa9d37d6fd9a24b4e5
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Mar 28 03:36:13 2011 +0400

    comment why we don't use temporary tables for mass ops

diff --git a/lib/DBIx/SearchBuilder/Handle/mysql.pm b/lib/DBIx/SearchBuilder/Handle/mysql.pm
index c300df2..f619139 100755
--- a/lib/DBIx/SearchBuilder/Handle/mysql.pm
+++ b/lib/DBIx/SearchBuilder/Handle/mysql.pm
@@ -107,6 +107,10 @@ sub SimpleMassChangeFromSelect {
     my $sth = $self->SimpleQuery( $search, @search_binds );
     return $sth unless $sth;
 
+
+    # tried TEMPORARY tables, much slower than fetching and delete
+    # also size of ENGINE=MEMORY is limitted by option, on disk
+    # tables more slower than in memory
     my $res = 0;
 
     my @ids;

-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list