[Bps-public-commit] dbix-searchbuilder branch, date-time-interval, created. 1.63-21-g99c09ee

Ruslan Zakirov ruz at bestpractical.com
Fri Mar 8 17:29:36 EST 2013


The branch, date-time-interval has been created
        at  99c09ee4838e3b69378c1e5db9231848ce1b4b6e (commit)

- Log -----------------------------------------------------------------
commit 99c09ee4838e3b69378c1e5db9231848ce1b4b6e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 8 22:45:15 2013 +0400

    Handle->DateTimeIntervalFunction method
    
    generates function call that calcs difference between
    two dates in seconds.

diff --git a/MANIFEST b/MANIFEST
index 44fbeb1..88a42c0 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -44,6 +44,7 @@ t/02distinct_values.t
 t/02order_outer.t
 t/02records_cachable.t
 t/02records_datetime.t
+t/02records_dt_interval.t
 t/02records_integers.t
 t/02records_object.t
 t/02searches_joins.t
diff --git a/lib/DBIx/SearchBuilder/Handle.pm b/lib/DBIx/SearchBuilder/Handle.pm
index ba0ddff..818b4a1 100755
--- a/lib/DBIx/SearchBuilder/Handle.pm
+++ b/lib/DBIx/SearchBuilder/Handle.pm
@@ -1593,6 +1593,22 @@ sub ConvertTimezoneFunction {
     return $args{'Field'};
 }
 
+=head2 DateTimeIntervalFunction
+
+Generates a function to calculate interval in seconds between two
+dates. Takes From and To arguments which can be either scalar or
+a hash. Hash is processed with L<DBIx::SearchBuilder/CombineFunctionWithField>.
+
+Arguments are not quoted or escaped in any way. It's caller's job.
+
+=cut
+
+sub DateTimeIntervalFunction {
+    my $self = shift;
+    my %args = ( From => undef, To => undef, @_ );
+    return 'NULL';
+}
+
 
 =head2 DESTROY
 
diff --git a/lib/DBIx/SearchBuilder/Handle/Oracle.pm b/lib/DBIx/SearchBuilder/Handle/Oracle.pm
index ad49eee..0b96d55 100755
--- a/lib/DBIx/SearchBuilder/Handle/Oracle.pm
+++ b/lib/DBIx/SearchBuilder/Handle/Oracle.pm
@@ -435,6 +435,17 @@ sub ConvertTimezoneFunction {
     return "FROM_TZ( CAST ($args{'Field'} AS TIMESTAMP), $args{'From'}) AT TIME ZONE $args{'To'}";
 }
 
+sub DateTimeIntervalFunction {
+    my $self = shift;
+    my %args = ( From => undef, To => undef, @_ );
+
+    my ($from, $to) = @args{'From', 'To'};
+    $_ = DBIx::SearchBuilder->CombineFunctionWithField(%$_)
+        for grep ref, $from, $to;
+
+    return "ROUND(( CAST( $to AS DATE ) - CAST( $from AS DATE ) ) * 86400)";
+}
+
 1;
 
 __END__
diff --git a/lib/DBIx/SearchBuilder/Handle/Pg.pm b/lib/DBIx/SearchBuilder/Handle/Pg.pm
index df32079..49a6333 100755
--- a/lib/DBIx/SearchBuilder/Handle/Pg.pm
+++ b/lib/DBIx/SearchBuilder/Handle/Pg.pm
@@ -325,6 +325,17 @@ sub ConvertTimezoneFunction {
     return $res;
 }
 
+sub DateTimeIntervalFunction {
+    my $self = shift;
+    my %args = ( From => undef, To => undef, @_ );
+
+    my ($from, $to) = @args{'From', 'To'};
+    $_ = DBIx::SearchBuilder->CombineFunctionWithField(%$_)
+        for grep ref, $from, $to;
+
+    return "EXTRACT(EPOCH FROM AGE($to, $from))";
+}
+
 1;
 
 __END__
diff --git a/lib/DBIx/SearchBuilder/Handle/SQLite.pm b/lib/DBIx/SearchBuilder/Handle/SQLite.pm
index b7985cb..e58843a 100644
--- a/lib/DBIx/SearchBuilder/Handle/SQLite.pm
+++ b/lib/DBIx/SearchBuilder/Handle/SQLite.pm
@@ -209,6 +209,17 @@ sub ConvertTimezoneFunction {
     return $res;
 }
 
+sub DateTimeIntervalFunction {
+    my $self = shift;
+    my %args = ( From => undef, To => undef, @_ );
+
+    my ($from, $to) = @args{'From', 'To'};
+    $_ = DBIx::SearchBuilder->CombineFunctionWithField(%$_)
+        for grep ref, $from, $to;
+
+    return "strftime('%s',$to) - strftime('%s',$from)";
+}
+
 1;
 
 __END__
diff --git a/lib/DBIx/SearchBuilder/Handle/mysql.pm b/lib/DBIx/SearchBuilder/Handle/mysql.pm
index 5c56ca9..b488dde 100755
--- a/lib/DBIx/SearchBuilder/Handle/mysql.pm
+++ b/lib/DBIx/SearchBuilder/Handle/mysql.pm
@@ -282,6 +282,17 @@ sub ConvertTimezoneFunction {
     return "CONVERT_TZ( $args{'Field'}, $args{'From'}, $args{'To'} )";
 }
 
+sub DateTimeIntervalFunction {
+    my $self = shift;
+    my %args = ( From => undef, To => undef, @_ );
+
+    my ($from, $to) = @args{'From', 'To'};
+    $_ = DBIx::SearchBuilder->CombineFunctionWithField(%$_)
+        for grep ref, $from, $to;
+
+    return "TIMESTAMPDIFF(SECOND, $from, $to)";
+}
+
 1;
 
 __END__
diff --git a/t/02records_dt_interval.t b/t/02records_dt_interval.t
new file mode 100644
index 0000000..ce0e6f3
--- /dev/null
+++ b/t/02records_dt_interval.t
@@ -0,0 +1,185 @@
+#!/usr/bin/perl -w
+
+BEGIN { $ENV{'TZ'} = 'Europe/Moscow' };
+
+use strict;
+use warnings;
+use Test::More;
+BEGIN { require "t/utils.pl" }
+our (@AvailableDrivers);
+
+use constant TESTS_PER_DRIVER => 15;
+
+my $total = scalar(@AvailableDrivers) * TESTS_PER_DRIVER;
+plan tests => $total;
+
+my $handle;
+
+foreach my $d ( @AvailableDrivers ) {
+SKIP: {
+    unless( has_schema( 'TestApp', $d ) ) {
+        skip "No schema for '$d' driver", TESTS_PER_DRIVER;
+    }
+    unless( should_test( $d ) ) {
+        skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
+    }
+
+    $handle = get_handle( $d );
+    connect_handle( $handle );
+    isa_ok($handle->dbh, 'DBI::db');
+
+    diag "testing $d" if $ENV{'TEST_VERBOSE'};
+
+    my $ret = init_schema( 'TestApp', $handle );
+    isa_ok($ret,'DBI::st', "Inserted the schema. got a statement handle back");
+
+    my $count_all = init_data( 'TestApp::User', $handle );
+    ok( $count_all,  "init users data" );
+
+    my $users = TestApp::Users->new( $handle );
+    $users->UnLimit;
+    $users->Column( FIELD => 'Result' );
+    my $column = $users->Column(
+        FUNCTION => $users->_Handle->DateTimeIntervalFunction( From => 'Created', To => 'Resolved' ),
+    );
+
+    while ( my $user = $users->Next ) {
+        is $user->__Value( $column ), $user->Result;
+    }
+
+    $users = TestApp::Users->new( $handle );
+    $users->UnLimit;
+    $users->Column( FIELD => 'Result' );
+    $column = $users->Column(
+        FUNCTION => $users->_Handle->DateTimeIntervalFunction(
+            From => { FIELD => 'Created' }, To => { FIELD => 'Resolved' },
+        ),
+    );
+
+    while ( my $user = $users->Next ) {
+        is $user->__Value( $column ), $user->Result;
+    }
+
+    cleanup_schema( 'TestApp', $handle );
+}} # SKIP, foreach blocks
+
+1;
+
+package TestApp;
+
+sub schema_mysql {
+<<EOF;
+CREATE TEMPORARY TABLE Users (
+    id integer AUTO_INCREMENT,
+    Created DATETIME NULL,
+    Resolved DATETIME NULL,
+    Result integer NULL,
+    PRIMARY KEY (id)
+)
+EOF
+
+}
+
+sub schema_pg {
+<<EOF;
+CREATE TEMPORARY TABLE Users (
+    id serial PRIMARY KEY,
+    Created TIMESTAMP NULL,
+    Resolved TIMESTAMP NULL,
+    Result integer NULL
+)
+EOF
+
+}
+
+sub schema_sqlite {
+
+<<EOF;
+CREATE TABLE Users (
+    id integer primary key,
+    Created TEXT NULL,
+    Resolved TEXT NULL,
+    Result integer NULL
+)
+EOF
+
+}
+
+sub schema_oracle { [
+    "CREATE SEQUENCE Users_seq",
+    "CREATE TABLE Users (
+        id integer CONSTRAINT Users_Key PRIMARY KEY,
+        Created DATE NULL,
+        Resolved DATE NULL,
+        Result integer NULL
+    )",
+] }
+
+sub cleanup_schema_oracle { [
+    "DROP SEQUENCE Users_seq",
+    "DROP TABLE Users",
+] }
+
+
+1;
+
+package TestApp::User;
+
+use base $ENV{SB_TEST_CACHABLE}?
+    qw/DBIx::SearchBuilder::Record::Cachable/:
+    qw/DBIx::SearchBuilder::Record/;
+
+sub _Init {
+    my $self = shift;
+    my $handle = shift;
+    $self->Table('Users');
+    $self->_Handle($handle);
+}
+
+sub _ClassAccessible {
+    {   
+        id =>
+        {read => 1, type => 'int(11)' }, 
+        Created =>
+        {read => 1, write => 1, type => 'datetime' },
+        Resolved =>
+        {read => 1, write => 1, type => 'datetime' },
+        Result =>
+        {read => 1, type => 'int(11)' }, 
+    }
+}
+
+sub init_data {
+    return (
+    [ 'Created',             'Resolved',           'Result'  ],
+    [ undef,                 undef                , undef ],
+    [ undef                , '2011-05-20 19:53:23', undef ],
+    [ '2011-05-20 19:53:23', undef                , undef ],
+    [ '2011-05-20 19:53:23', '2011-05-20 19:53:23', 0],
+    [ '2011-05-20 19:53:23', '2011-05-21 20:54:24', 1*24*60*60+1*60*60+1*60+1],
+    [ '2011-05-20 19:53:23', '2011-05-19 18:52:22', -(1*24*60*60+1*60*60+1*60+1)],
+    );
+}
+
+1;
+
+package TestApp::Users;
+
+# use TestApp::User;
+use base qw/DBIx::SearchBuilder/;
+
+sub _Init {
+    my $self = shift;
+    $self->SUPER::_Init( Handle => shift );
+    $self->Table('Users');
+}
+
+sub NewItem
+{
+    my $self = shift;
+    return TestApp::User->new( $self->_Handle );
+}
+
+1;
+
+

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



More information about the Bps-public-commit mailing list