Ruby ActiveRecord/sqlite3列类型在表视图中丢失?

Ruby ActiveRecord/sqlite3列类型在表视图中丢失?,ruby,activerecord,sqlite,types,Ruby,Activerecord,Sqlite,Types,我有下面的ActiveRecord测试用例,它模拟了我的问题。我有一个人员表,其中一个属性是日期。我在该表上创建了一个视图,添加了一列,正好是该日期加上20分钟: #!/usr/bin/env ruby %w|pp rubygems active_record irb active_support date|.each {|lib| require lib} ActiveRecord::Base.establish_connection( :adapter => "sqlite3",

我有下面的ActiveRecord测试用例,它模拟了我的问题。我有一个人员表,其中一个属性是日期。我在该表上创建了一个视图,添加了一列,正好是该日期加上20分钟:

#!/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
当我期望视图的新datetime属性也是ruby世界中的一个时间或datetime时。有什么想法吗

我还尝试:

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

同样的结果。

经过进一步调查,我发现:

MySQL的工作原理:

%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
阅读sqlite3适配器源代码时,我发现它使用PRAGMA table_infotable_name来获取类型信息,并且不会返回视图的类型:

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
因此,这可能是适配器的限制,也可能只是sqlite3的视图限制。我有:

此外,在sqlite用户中:

RoR应该使用 sqlite3\u列\u类型API确定 从数据库返回的值的类型 查询其他API如 sqlite3_列_decltype和pragma 表_信息正在返回其他信息 信息,而不是 结果值


好的,与MySQL相比,SQLite中基本上没有数据时间类型。在您的示例中,您明确定义了表的类型,但没有指定视图的类型。这可能就是问题所在。无法检查它,因为我从未接触过ruby。

问题是RoR和sqlite3。第一种方法在知道sqlite3无法提供视图类型时,使用table_info PRAGMA作为视图。它应该在结果集上使用sqlite3_column_type,但似乎ActiveRecord中的类型对于一个表只解析一次。Sqlite的错误在于没有在视图中提供类型,而这些类型可以映射到源表,在这种情况下,至少可以映射到datetime函数MySQL的结果。
Time
Time
Time
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