Fixed date filters accuracy with SQLite (#2221).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2054 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2008-11-23 16:40:35 +00:00
parent 06266c8fec
commit 9e1192a54d
3 changed files with 84 additions and 16 deletions

View File

@ -329,19 +329,19 @@ class Query < ActiveRecord::Base
when "c" when "c"
sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_true}" if field == "status_id" sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_true}" if field == "status_id"
when ">t-" when ">t-"
sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today - v.first.to_i).to_time), connection.quoted_date((Date.today + 1).to_time)] sql = sql + date_range_clause(db_table, db_field, - v.first.to_i, 0)
when "<t-" when "<t-"
sql = sql + "#{db_table}.#{db_field} <= '%s'" % connection.quoted_date((Date.today - v.first.to_i).to_time) sql = sql + date_range_clause(db_table, db_field, nil, - v.first.to_i)
when "t-" when "t-"
sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today - v.first.to_i).to_time), connection.quoted_date((Date.today - v.first.to_i + 1).to_time)] sql = sql + date_range_clause(db_table, db_field, - v.first.to_i, - v.first.to_i)
when ">t+" when ">t+"
sql = sql + "#{db_table}.#{db_field} >= '%s'" % connection.quoted_date((Date.today + v.first.to_i).to_time) sql = sql + date_range_clause(db_table, db_field, v.first.to_i, nil)
when "<t+" when "<t+"
sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Date.today.to_time), connection.quoted_date((Date.today + v.first.to_i + 1).to_time)] sql = sql + date_range_clause(db_table, db_field, 0, v.first.to_i)
when "t+" when "t+"
sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date((Date.today + v.first.to_i).to_time), connection.quoted_date((Date.today + v.first.to_i + 1).to_time)] sql = sql + date_range_clause(db_table, db_field, v.first.to_i, v.first.to_i)
when "t" when "t"
sql = sql + "#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [connection.quoted_date(Date.today.to_time), connection.quoted_date((Date.today+1).to_time)] sql = sql + date_range_clause(db_table, db_field, 0, 0)
when "w" when "w"
from = l(:general_first_day_of_week) == '7' ? from = l(:general_first_day_of_week) == '7' ?
# week starts on sunday # week starts on sunday
@ -382,4 +382,16 @@ class Query < ActiveRecord::Base
@available_filters["cf_#{field.id}"] = options.merge({ :name => field.name }) @available_filters["cf_#{field.id}"] = options.merge({ :name => field.name })
end end
end end
# Returns a SQL clause for a date or datetime field.
def date_range_clause(table, field, from, to)
s = []
if from
s << ("#{table}.#{field} > '%s'" % [connection.quoted_date((Date.yesterday + from).to_time.end_of_day)])
end
if to
s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date((Date.today + to).to_time.end_of_day)])
end
s.join(' AND ')
end
end end

View File

@ -91,4 +91,21 @@ issues_006:
status_id: 1 status_id: 1
start_date: <%= Date.today.to_s(:db) %> start_date: <%= Date.today.to_s(:db) %>
due_date: <%= 1.days.from_now.to_date.to_s(:db) %> due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
issues_007:
created_on: <%= 10.days.ago.to_date.to_s(:db) %>
project_id: 1
updated_on: <%= 10.days.ago.to_date.to_s(:db) %>
priority_id: 3
subject: Issue due today
id: 7
fixed_version_id:
category_id:
description: This is an issue that is due today
tracker_id: 1
assigned_to_id:
author_id: 2
status_id: 1
start_date: <%= 10.days.ago.to_s(:db) %>
due_date: <%= Date.today.to_s(:db) %>
lock_version: 0

View File

@ -18,7 +18,7 @@
require File.dirname(__FILE__) + '/../test_helper' require File.dirname(__FILE__) + '/../test_helper'
class QueryTest < Test::Unit::TestCase class QueryTest < Test::Unit::TestCase
fixtures :projects, :users, :members, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries fixtures :projects, :enabled_modules, :users, :members, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :versions, :queries
def test_custom_fields_for_all_projects_should_be_available_in_global_queries def test_custom_fields_for_all_projects_should_be_available_in_global_queries
query = Query.new(:project => nil, :name => '_') query = Query.new(:project => nil, :name => '_')
@ -75,37 +75,76 @@ class QueryTest < Test::Unit::TestCase
end end
def test_operator_in_more_than def test_operator_in_more_than
Issue.find(7).update_attribute(:due_date, (Date.today + 15))
query = Query.new(:project => Project.find(1), :name => '_') query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', '>t+', ['15']) query.add_filter('due_date', '>t+', ['15'])
assert query.statement.include?("#{Issue.table_name}.due_date >=") issues = find_issues_with_query(query)
find_issues_with_query(query) assert !issues.empty?
issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
end end
def test_operator_in_less_than def test_operator_in_less_than
query = Query.new(:project => Project.find(1), :name => '_') query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', '<t+', ['15']) query.add_filter('due_date', '<t+', ['15'])
assert query.statement.include?("#{Issue.table_name}.due_date BETWEEN") issues = find_issues_with_query(query)
find_issues_with_query(query) assert !issues.empty?
issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
end
def test_operator_less_than_ago
Issue.find(7).update_attribute(:due_date, (Date.today - 3))
query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', '>t-', ['3'])
issues = find_issues_with_query(query)
assert !issues.empty?
issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
end
def test_operator_more_than_ago
Issue.find(7).update_attribute(:due_date, (Date.today - 10))
query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', '<t-', ['10'])
assert query.statement.include?("#{Issue.table_name}.due_date <=")
issues = find_issues_with_query(query)
assert !issues.empty?
issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
end
def test_operator_in
Issue.find(7).update_attribute(:due_date, (Date.today + 2))
query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', 't+', ['2'])
issues = find_issues_with_query(query)
assert !issues.empty?
issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
end
def test_operator_ago
Issue.find(7).update_attribute(:due_date, (Date.today - 3))
query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', 't-', ['3'])
issues = find_issues_with_query(query)
assert !issues.empty?
issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
end end
def test_operator_today def test_operator_today
query = Query.new(:project => Project.find(1), :name => '_') query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', 't', ['']) query.add_filter('due_date', 't', [''])
assert query.statement.include?("#{Issue.table_name}.due_date BETWEEN") issues = find_issues_with_query(query)
find_issues_with_query(query) assert !issues.empty?
issues.each {|issue| assert_equal Date.today, issue.due_date}
end end
def test_operator_this_week_on_date def test_operator_this_week_on_date
query = Query.new(:project => Project.find(1), :name => '_') query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('due_date', 'w', ['']) query.add_filter('due_date', 'w', [''])
assert query.statement.include?("#{Issue.table_name}.due_date BETWEEN")
find_issues_with_query(query) find_issues_with_query(query)
end end
def test_operator_this_week_on_datetime def test_operator_this_week_on_datetime
query = Query.new(:project => Project.find(1), :name => '_') query = Query.new(:project => Project.find(1), :name => '_')
query.add_filter('created_on', 'w', ['']) query.add_filter('created_on', 'w', [''])
assert query.statement.include?("#{Issue.table_name}.created_on BETWEEN")
find_issues_with_query(query) find_issues_with_query(query)
end end