使用DBIC提取日期部分,同时保持查询数据库不可知

时间:2016-01-09 10:55:48

标签: perl datetime dbix-class database-agnostic

我在生产中使用MySQL数据库,在运行测试时使用SQLite数据库。我的应用程序的一部分用于收集一年的月度统计数据。我已经成功完成了这项工作,但这是以无法自动化测试为代价的,因为我在查询数据时使用的是MySQL特定功能:

my $criteria = {
    status => ['Complete'],
    'YEAR(completed_on)' => DateTime->now()->year(),
};

my $attributes = {
    select => [ { count => 'title' }, 'completed_on' ],
    as => [qw/num_completed datetime/],
    group_by => [qw/MONTH(completed_on)/],
};

注意我正在使用YEARMONTH MySQL函数。

我知道一种方法可以替换where子句来消除使用MySQL YEAR函数,如下所示:

my $dtf = $schema->storage->datetime_parser;
my $begin_date = DateTime->from_day_of_year( year => DateTime->now()->year(), day_of_year => 1 ); #inception o_O
my $end_date = DateTime->from_day_of_year( year => DateTime->now()->year(), day_of_year => 36[56] );

my $criteria = {
    status => ['Complete'],
    completed_on =>
    -between => [
        $dtf->format_datetime($begin_date),
        $dtf->format_datetime($end_date),
    ]
};

Using the recommended way to query date fields using DBIC

但是我对如何处理group_by子句以及如何对这些字段进行分组以及按月数据库不可知的方式进行分组感到困惑。想知道是否有人有任何想法?

谢谢!

1 个答案:

答案 0 :(得分:1)

如果您尝试做特殊事情,有时您必须在DBIx :: Class中制作特定于引擎的代码。您可以使用$schema->storage->sqlt_type制作不同的SQL。

请注意,您也可以使用substr(completed_on,1,4)来获取SQLite中的年份。

这将解决您的问题:

my $type = $schema->storage->sqlt_type;

my $criteria;
my $attributes;

if ($type eq 'MySQL') {
    $criteria = {
        status => ['Complete'],
        'YEAR(completed_on)' => DateTime->now()->year(),
    };

    $attributes = {
        select => [ { count => 'title' }, 'completed_on' ],
        as => [qw/num_completed datetime/],
        group_by => [qw/MONTH(completed_on)/],
    };
}
elsif ($type eq 'SQLite') {
    my $dtf = $schema->storage->datetime_parser;
    my $begin_date = DateTime->from_day_of_year( year => DateTime->now()->year(), day_of_year => 1 ); #inception o_O
    my $end_date = DateTime->from_day_of_year( year => DateTime->now()->year() + 1, day_of_year => 1 )->add( seconds => -1 );

    $criteria = {
        status => ['Complete'],
        completed_on => {
            -between => [
                $dtf->format_datetime($begin_date),
                $dtf->format_datetime($end_date),
            ]
        }
    };

    $attributes = {
        select => [ { count => 'title' }, 'completed_on' ],
        as => [qw/num_completed datetime/],
        group_by => ['substr(completed_on,6,2)'],
    };
}