Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8935101
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T09:55:14+00:00 2026-06-15T09:55:14+00:00

I’m trying to find a database agnostic way of comparing dates with active record

  • 0

I’m trying to find a database agnostic way of comparing dates with active record queries. I’ve the following query:

UserRole.where("(effective_end_date - effective_start_date) > ?", 900.seconds)

This works fine on MySQL but produces an error on PG as the sql it generates doesn’t contain the ‘interval’ syntax. From the console:

  ←[1m←[36mUserRole Load (2.0ms)←[0m  ←[1mSELECT "user_roles".* FROM "user_roles" WHERE "user_roles"."effective_end_date" IS NULL AND ((effective_end_d
ate - effective_start_date) > '--- 900
...
')←[0m
ActiveRecord::StatementInvalid: PG::Error: ERROR:  invalid input syntax for type interval: "--- 900

When I run this with the to_sql I option I get:

irb(main):001:0> UserRole.where("effective_end_date - effective_start_date) > ?", 900.seconds).to_sql
=> "SELECT \"user_roles\".* FROM \"user_roles\"  WHERE \"user_roles\".\"effective_end_date\" IS NULL AND (effective_end_date - effective_start_date) >
'--- 900\n...\n')"

All help appreciated.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T09:55:15+00:00Added an answer on June 15, 2026 at 9:55 am

    If your effective_end_date and effective_start_date columns really are dates then your query is pointless because dates have a minimum resolution of one day and 900s is quite a bit smaller than 86400s (AKA 25*60*60 or 1 day). So I’ll assume that your “date” columns are actually datetime (AKA timestamp) columns; if this is true then you might want to rename the columns to avoid confusion during maintenance, effectively_starts_at and effectively_ends_at would probably be good matches for the usual Rails conventions. If this assumption is invalid then you should change your column types or stop using 900s.

    Back to the real problem. ActiveRecord converts Ruby values to SQL values using the ActiveRecord::ConnectionAdapters::Quoting#quote method:

    def quote(value, column = nil)
      # records are quoted as their primary key
      return value.quoted_id if value.respond_to?(:quoted_id)
    
      case value
      #...
      else
        "'#{quote_string(YAML.dump(value))}'"
      end
    end
    

    So if you try to use something as a value for a placeholder and there isn’t any specific handling built in for that type, then you get YAML (a bizarre choice of defaults IMO). Also, 900.seconds is an ActiveSupport::Duration object (despite what 900.seconds.class says) and the case value has no branch for ActiveSupport::Duration so 900.seconds will get YAMLified.

    The PostgreSQL adapter provides its own quote in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#quote but that doesn’t know about ActiveSupport::Duration either. The MySQL adapter’s quote is also ignorant of ActiveSupport::Duration. You could monkey patch some sense into these quote methods. Something like this in an initializer:

    class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
        # Grab an alias for the standard quote method
        alias :std_quote :quote
        # Bludgeon some sense into things
        def quote(value, column = nil)
            return "interval '#{value.to_i} seconds'" if(value.is_a?(ActiveSupport::Duration))
            std_quote(value, column)
        end
    end
    

    With that patch in place, you get intervals that PostgreSQL understands when you use an ActiveSupport::Duration:

    > Model.where('a - b > ?', 900.seconds).to_sql
     => "SELECT \"models\".* FROM \"models\"  WHERE (a - b > interval '900 seconds')" 
    > Model.where('a - b > ?', 11.days).to_sql
     => "SELECT \"models\".* FROM \"models\"  WHERE (a - b > interval '950400 seconds')"
    

    If you add a similar patch to the MySQL adapter’s quote (which is left as an exercise for the reader), then things like:

    UserRole.where("(effective_end_date - effective_start_date) > ?", 900.seconds)
    

    will do The Right Thing in both PostgreSQL and MySQL and your code won’t have to worry about it.


    That said, developing and deploying on different databases is a really bad idea that will make Santa Claus cry and go looking for some coal (possibly laced with arsenic, possibly radioactive) for your stocking. So don’t do that.

    If on the other hand you’re trying to build database-agnostic software, then you’re in for some happy fun times! Database portability is largely a myth and database-agnostic software always means writing your own portability layer on top of the ORM and database interfaces that your platform provides. You will have to exhaustively test everything on each database you plan to support, everyone pays lip service to the SQL Standard but no one seems to fully support it and everyone has their own extensions and quirks to worry about. You will end up writing your own portability layer that will consist of a mixture of utility methods and monkey patches.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to convert HTML to plain text. I get many &\#8217; &\#8220; etc.
Let's say I'm outputting a post title and in our database, it's Hello Y’all
I am trying to understand how to use SyndicationItem to display feed which is
Basically, what I'm trying to create is a page of div tags, each has
I have a string like this: La Torre Eiffel paragonata all’Everest What PHP function
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I am trying to render a haml file in a javascript response like so:
I'm using v2.0 of ClassTextile.php, with the following call: $testimonial_text = $textile->TextileRestricted($_POST['testimonial']); ... and
I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
I'm trying to select an H1 element which is the second-child in its group

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.