This project is archived and is in readonly mode.

#4544 ✓wontfix
Duncan Mac-Vicar

rails3 : ActiveRecord sqlite3 : lost column type when using views

Reported by Duncan Mac-Vicar | May 6th, 2010 @ 09:23 PM

Originally I asked in Stackoverflow until I realized MySQL adapter does work correctly.

Rails 3.0.0.beta3 with ruby 1.9.2head (happens in 2.3.5 / ruby 1.8.7 too)

DATETIME columns in sqlite3 are interpreted as Time/TimeWithZone objects. However, when using a view over a table where the adapter already interprets the time column type correctly, you get a String instead:

    #!/usr/bin/env ruby

    %w|pp rubygems active_record irb active_support date|.each {|lib| require lib}

    ActiveRecord::Base.establish_connection(
    :adapter => "sqlite3",
    :database => "test.db"
    )

    ActiveRecord::Schema.define do
      create_table :people, :force => true do |t|
        t.column :name, :string
        t.column :born_at, :datetime
      end

      execute "create view clowns as select p.name, p.born_at, datetime(p.born_at, '+' || '20' || ' minutes') as     twenty_after_born_at from people p;"

    end

    class Person < ActiveRecord::Base
      validates_presence_of :name
    end

    class Clown < ActiveRecord::Base
    end

    Person.create(:name => "John", :born_at => DateTime.now)

    pp Person.all.first.born_at.class
    pp Clown.all.first.born_at.class
    pp Clown.all.first.twenty_after_born_at.class

Produces output:

Time
Time
String

The same case in MySQL:

    #!/usr/bin/env ruby

    %w|pp rubygems active_record irb active_support date|.each {|lib| require lib}

    ActiveRecord::Base.establish_connection(
        :adapter => "mysql",
        :username => "root",
        :database => "test2"
    )

    ActiveRecord::Schema.define do
      create_table :people, :force => true do |t|
        t.column :name, :string
        t.column :born_at, :datetime
      end

      execute "create view clowns as select p.name, p.born_at, (p.born_at + INTERVAL 20 MINUTE) as twenty_after_born_at from people p;"
    end

    class Person < ActiveRecord::Base
      validates_presence_of :name
    end

    class Clown < ActiveRecord::Base
    end

    Person.create(:name => "John", :born_at => DateTime.now)

    pp Person.all.first.born_at.class
    pp Clown.all.first.born_at.class
    pp Clown.all.first.twenty_after_born_at.class

Produces output:

Time
Time
Time

Which is what I expect.

Comments and changes to this ticket

  • Duncan Mac-Vicar

    Duncan Mac-Vicar May 6th, 2010 @ 09:41 PM

    The problem seems to come from the fact that the adapter uses PRAGMA table_info(table_name) to get the type information, and that does not return the types for views:

    sqlite> pragma table_info('people');
    0|id|INTEGER|1||1
    1|name|varchar(255)|0||0
    2|born_at|datetime|0||0
    sqlite> pragma table_info('clowns');
    0|name|varchar(255)|0||0
    1|born_at|datetime|0||0
    2|twenty_after_born_at||0||0
    

    However, as I said, it works in MySQL.

  • Duncan Mac-Vicar

    Duncan Mac-Vicar May 6th, 2010 @ 10:13 PM

    Also, quoting this mail in sqlite-users:

    RoR should be using the sqlite3_column_type() API to determine the type of the values returned from a query. Other APIs like sqlite3_column_decltype() and pragma table_info are returning other information, not the type of the result value.

  • Duncan Mac-Vicar

    Duncan Mac-Vicar May 6th, 2010 @ 10:13 PM

    Also, quoting this mail in sqlite-users:

    RoR should be using the sqlite3_column_type() API to determine the type of the values returned from a query. Other APIs like sqlite3_column_decltype() and pragma table_info are returning other information, not the type of the result value.

  • Dan Pickett

    Dan Pickett May 9th, 2010 @ 06:47 PM

    • Tag changed from sqlite3 activerecord to activerecord, bugmash, sqlite3
  • Diego Algorta

    Diego Algorta May 15th, 2010 @ 09:31 PM

    This is not a rails bug. It's a bug in sqlite3-ruby gem itself. I glanced at their code in current master and they're still using PRAGMA so I reported the bug in http://rubyforge.org/tracker/index.php?func=detail&amp;aid=28203&am...

  • Aaron Patterson

    Aaron Patterson May 15th, 2010 @ 09:37 PM

    • Assigned user changed from “Jeremy Kemper” to “Aaron Patterson”
  • Aaron Patterson

    Aaron Patterson June 17th, 2010 @ 12:42 AM

    • State changed from “new” to “wontfix”

    This can't be fixed. The sqlite3_column_type() function can't tell the difference between a column declared as a datetime vs a string as datetimes are actually stored as strings in sqlite. The pragma call is the only way to get the declared column types and it unfortunately doesn't work with views.

    See the sqlite3 C api for sqlite3_column_type():

    http://www.sqlite.org/capi3ref.html#sqlite3_column_blob

    Also see my comments on the rubyforge ticket.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages