gpt4 book ai didi

postgresql - PostgreSQL 中的 Activerecord-import & serial 列

转载 作者:行者123 更新时间:2023-11-29 12:00:59 26 4
gpt4 key购买 nike

我正在将 Rails 2.3.4 项目升级到 Rails 3.1.1。旧版本使用 ar-extensions 来处理数据导入。我拔出了 ar-extensions 并将其替换为 activerecord-import,我知道它具有完全相同的接口(interface)。

我的代码调用是这样的

Student.import(columns, values)

两个 args 都是保存正确数据的有效数组,但我得到了一个大错误!

错误堆栈如下所示:

NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.split):
activerecord (3.1.1) lib/active_record/connection_adapters/postgresql_adapter.rb:828:in 'default_sequence_name'
activerecord (3.1.1) lib/active_record/base.rb:647:in `reset_sequence_name'
activerecord (3.1.1) lib/active_record/base.rb:643:in `sequence_name'
activerecord-import (0.2.9) lib/activerecord-import/import.rb:203:in `import'

查看代码,似乎 Activerecord-import 调用了 activerecord,后者依次查找 Postgres 序列的名称和下一个值。

因此 activerecord-import 查找 sequence_namelib/activerecord-import/import.rb:203

# Force the primary key col into the insert if it's not
# on the list and we are using a sequence and stuff a nil
# value for it into each row so the sequencer will fire later
-> if !column_names.include?(primary_key) && sequence_name && connection.prefetch_primary_key?
column_names << primary_key
array_of_attributes.each { |a| a << nil }
end

它调用事件记录...lib/active_record/base.rb:647:in `reset_sequence_name'

# Lazy-set the sequence name to the connection's default. This method
# is only ever called once since set_sequence_name overrides it.
def sequence_name #:nodoc:
-> reset_sequence_name
end

def reset_sequence_name #:nodoc:
-> default = connection.default_sequence_name(table_name, primary_key)
set_sequence_name(default)
default
end

serial_sequence 返回 nil 并且 default_sequence_name 试图拆分它时,代码错误。

lib/active_record/connection_adapters/postgresql_adapter.rb

# Returns the sequence name for a table's primary key or some other specified key.
def default_sequence_name(table_name, pk = nil) #:nodoc:
-> serial_sequence(table_name, pk || 'id').split('.').last
rescue ActiveRecord::StatementInvalid
"#{table_name}_#{pk || 'id'}_seq"
end

def serial_sequence(table, column)
result = exec_query(<<-eosql, 'SCHEMA', [[nil, table], [nil, column]])
SELECT pg_get_serial_sequence($1, $2)
eosql
result.rows.first.first
end

当我直接对数据库执行 pg_get_serial_sequence() 时,我没有得到任何返回值:

SELECT pg_get_serial_sequence('student', 'id')

但是我可以看到在数据库中有一个序列叫做student_id_seq

我正在使用以下版本的 Ruby、rails PG 等。

  • 轨道 3.1.1
  • ruby 1.9.2
  • Activerecord-import 0.2.9
  • 第 0.12.2 页
  • psql(9.0.5,服务器 9.1.3)

我已经将数据库从 MySQL 迁移到 PostgreSQL,我认为这对问题没有任何影响,但我认为为了完整性我最好添加它。

我不明白为什么这不起作用!

最佳答案

您的描述摘要:

  • student 表存在。
  • id 列存在。
  • 序列 student_id_seq 存在。
  • pg_get_serial_sequence('student', 'id') 仍然返回 NULL

两种可能的解释:

1) 序列未链接到该列。

列默认值和列与序列之间的联系是独立的特征。拟合序列的存在并不意味着它会按照您的假设进行。但是,如果您将列创建为 serial,您将获得整个包。阅读the details in the manual .

要解决此问题(如果您确定它应该如此),您可以将序列标记为“拥有者”student.id:

ALTER SEQUENCE student_id_seq OWNED BY student.id;

同时检查列默认值是否按预期设置:

SELECT column_name, column_default
FROM information_schema.columns
WHERE table_name = 'student'
-- AND schema = 'your_schema' -- if needed

如果不行,修复:

ALTER TABLE student ALTER COLUMN id SET DEFAULT nextval('student.id')

2) 主机地址/端口/数据库/模式/表名大小写的混合

它一直在发生。确保检查您的应用程序连接到的相同数据库,使用相同的用户或至少相同的 search_path .确保对象位于您期望的架构中,并且没有例如另一个架构中的另一个 student 表混淆。

关于postgresql - PostgreSQL 中的 Activerecord-import & serial 列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9737270/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com