ActiveRecord的进口和放大器;在PostgreSQL的连载专栏 [英] Activerecord-import & serial column in PostgreSQL

查看:269
本文介绍了ActiveRecord的进口和放大器;在PostgreSQL的连载专栏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在升级的Rails 2.3.4项目到Rails 3.1.1的过程。旧版本中使用AR-扩展处理数据导入。我掏出AR-扩展和与ActiveRecord的进口,这点我明白了完全相同的接口。

I am in the process of upgrading a Rails 2.3.4 project to Rails 3.1.1. The old version used ar-extensions to handle a data import. I pulled out ar-extensions and replaced it with activerecord-import, which I understand has exactly the same interfaces.

我的code调用看起来像这样

My code calls looks like this

Student.import(columns, values)

两者的args是保持正确的数据有效阵列,但我得到一个大胖子的错误!

Both args are valid arrays holding the correct data, but I get a big fat error!

错误堆栈看起来是这样的:

The error stack looks like this:

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'

翻翻code却仿佛ActiveRecord的进口要求的ActiveRecord从而查找名称和Postgres的序列的下一个值。

Looking through the code it seems as though Activerecord-import calls activerecord which in turn looks for the name and next value of the Postgres sequence.

所以ActiveRecord的导入查找SEQUENCE_NAME LIB / ActiveRecord的导入/ import.rb:203

So activerecord-import looks for the sequence_name lib/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:在'reset_sequence_name

It calls active record ... 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 试图拆分它。

The code errors when serial_sequence returns nil and default_sequence_name tries to split it.

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()直接对我没有得到任何返回值的数据库:

When I execute pg_get_serial_sequence() directly against the database I get no value returned:

SELECT pg_get_serial_sequence('student', 'id')

不过,我可以看到,在数据库中有一个序列名为 student_id_seq

我使用的红宝石以下版本,轨道PG等。

I am using the following versions of Ruby, rails PG etc..

  • 的Rails 3.1.1
  • 的Ruby 1.9.2
  • ActiveRecord的进口0.2.9
  • 第0.12.2提供
  • 在PSQL(9.0.5,9.1.3服务器)

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

I have migrated the database from MySQL to PostgreSQL, I don't think this has any bearing on the problem but I thought that I'd better add it for completeness.

我不明白为什么这是行不通的!

I can't work out why this isn't working!

推荐答案

  • 学生的存在。
  • 在列 ID 的存在。
  • 顺序 student_id_seq 的存在。
  • pg_get_serial_sequence('学生','ID')仍返回 NULL

Summary of your description:

  • The table student exists.
  • The column id exists.
  • The sequence student_id_seq exists.
  • pg_get_serial_sequence('student', 'id') still returns NULL.
  • 1)顺序为不挂以列。

    默认列与列和序列之间的联系是独立的功能。仅仅存在一个合适的顺序并不意味着它做什么,你presume。如果您创建一个列系列你全包,但。阅读在手动的细节。

    Column default and the tie between column and sequence are independent features. The mere existence of a fitting sequence does not mean it does what you presume. If you create a column as serial you get the whole package, though. Read the details in the manual.

    要解决这个问题(如果你确信这是应该的),你可以标记的顺序为归 student.id

    To fix this (and if you are sure that's how it should be), you can mark the sequence as "owned by" student.id:

    ALTER SEQUENCE student_id_seq OWNED BY student.id;
    

    另外检查列默认设置为预期的:

    Also check if the column default is set as expected:

    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)的的mixup 表名的主机地址/端口/数据库/模式/资本化。

    2) A mixup of host address / port / database / schema / capitalization of the table name.

    这一切发生的时间。请确保您检查您的应用程序连接到同一个数据库,使用相同的用户或者至少是相同的 SEARCH_PATH 。确保的对象是在你所期望的模式并没有,比如,另一个学生表中的搞混了另一种模式。

    It happens all the time. Make sure you check the same database that your app connects to, With the same user or at least the same search_path. Make sure, the objects are in the schema where you expect them and there isn't, for instance, another student table in another schema that got mixed up.

    这篇关于ActiveRecord的进口和放大器;在PostgreSQL的连载专栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆