diff --git a/app/models/queries/operators/date_limits.rb b/app/models/queries/operators/date_limits.rb new file mode 100644 index 000000000000..51f6ad440b93 --- /dev/null +++ b/app/models/queries/operators/date_limits.rb @@ -0,0 +1,46 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module Queries::Operators + module DateLimits + # Technically dates in PostgreSQL can be up to 5874897 AD, but limit to + # timestamp range, as dates are used to query for timestamps too + # + # https://www.postgresql.org/docs/current/datatype-datetime.html + PG_DATE_FROM = ::Date.new(-4713, 1, 1) + PG_DATE_TO_EXCLUSIVE = ::Date.new(294276 + 1, 1, 1) + + def date_too_small?(date) + date < PG_DATE_FROM + end + + def date_too_big?(date) + date >= PG_DATE_TO_EXCLUSIVE + end + end +end diff --git a/app/models/queries/operators/date_range_clauses.rb b/app/models/queries/operators/date_range_clauses.rb index 924cfbd7b3a1..81e9adaf5233 100644 --- a/app/models/queries/operators/date_range_clauses.rb +++ b/app/models/queries/operators/date_range_clauses.rb @@ -28,6 +28,8 @@ module Queries::Operators module DateRangeClauses + include DateLimits + # Returns a SQL clause for a date or datetime field for a relative range from # the end of the day of yesterday + from until the end of today + to. def relative_date_range_clause(table, field, from, to) @@ -45,11 +47,25 @@ def date_range_clause(table, field, from, to) s = [] if from - s << ("#{table}.#{field} > '%s'" % [quoted_date_from_utc(from.yesterday)]) + s << case + when date_too_small?(from) + "1 = 1" + when date_too_big?(from) + "1 <> 1" + else + "#{table}.#{field} > '#{quoted_date_from_utc(from.yesterday)}'" + end end if to - s << ("#{table}.#{field} <= '%s'" % [quoted_date_from_utc(to)]) + s << case + when date_too_small?(to) + "1 <> 1" + when date_too_big?(to) + "1 = 1" + else + "#{table}.#{field} <= '#{quoted_date_from_utc(to)}'" + end end s.join(" AND ") diff --git a/app/models/queries/operators/datetime_range_clauses.rb b/app/models/queries/operators/datetime_range_clauses.rb index b9a248f8dc72..c754716fd2a1 100644 --- a/app/models/queries/operators/datetime_range_clauses.rb +++ b/app/models/queries/operators/datetime_range_clauses.rb @@ -28,15 +28,31 @@ module Queries::Operators module DatetimeRangeClauses + include DateLimits + def datetime_range_clause(table, field, from, to) s = [] if from - s << ("#{table}.#{field} >= '%s'" % [connection.quoted_date(from)]) + s << case + when date_too_small?(from) + "1 = 1" + when date_too_big?(from) + "1 <> 1" + else + "#{table}.#{field} >= '#{connection.quoted_date(from)}'" + end end if to - s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date(to)]) + s << case + when date_too_small?(to) + "1 <> 1" + when date_too_big?(to) + "1 = 1" + else + "#{table}.#{field} <= '#{connection.quoted_date(to)}'" + end end s.join(" AND ")