Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP


ActiveRecord >=3.1 / setting primary_key to an column defined in the db as auto-increment but not primary key #3987

kjg opened this Issue · 11 comments

2 participants


When using a legacy database or when writing to a view, if a column is set to auto-increment, but the schema doesn't define it as a "primary key", then active record fails to properly set the primary_key column in the schema_cache early enough.

It looks like by calling #create, the schema_cache's colums are filled before AR:Base#columns gets called. #columns being the method that sets the primary_key in the cache

I've included a failing test as well as a proposed fix in this gist.

In my opinion #columns is probably not the place to be putting the primary_key in the cache though since clearly the column definitions in the cache are filled before #columns is called. A better fix would be to either 1. find a better time earlier in the query life cycle to cache the primary_key as set by AR, or 2. cache the column definitions later in the query cycle.


FYI: This issue was caused by this patch's attempt to fix this issue

@jonleighton jonleighton was assigned
@jonleighton jonleighton closed this issue from a commit
@jonleighton jonleighton Fix #3987.

@SweeD SweeD referenced this issue from a commit in mafolz/rails
@jonleighton jonleighton Fix #3987. 8dba32f

Just curious. Why didn't you remove the similar code from #columns?


Because that would bring back bug #2807.


How so? Doesn't the if connected? fix that?



-- $ git diff
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 9215a68..511292a 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -767,10 +767,6 @@ module ActiveRecord #:nodoc:

       # Returns an array of column objects for the table associated with this class.
       def columns
-        if defined?(@primary_key)
-          connection.schema_cache.primary_keys[table_name] ||= primary_key
-        end

-- $ ruby -Itest test/cases/primary_keys_test.rb -n test_set_primary_key_with_no_connection
Using sqlite3 with Identity Map off
Loaded suite test/cases/primary_keys_test
Finished in 0.006121 seconds.

1 tests, 2 assertions, 0 failures, 0 errors, 0 skips

Test run options: --seed 36004 --name "test_set_primary_key_with_no_connection"

Yes but now when you call Model.columns none of the items will have primary == true. The test doesn't show this though.


Okay, if thats true, then this current issue will still exist if the Model is loaded when the db is not connected, then the db connects, then queries are run.


that's what the if defined?(@primary_key) ... in columns is for - in case you set the primary key before a connection existed. that's why we can't delete it.


Yes, but that means this bug, bug 3987 isn't fixed. I'll write up a new script to prove it to you.


Your changes this morning on master fixes this bug there. However 3-1-stable still fails with this new test:

## must run activerecord's `rake postgresql:build_databases`
require 'active_record'

ActiveRecord::Base.establish_connection(:adapter => 'postgresql', :database => 'activerecord_unittest')

ActiveRecord::Schema.define do
  execute <<_SQL
    CREATE SEQUENCE foo_seq;
    CREATE TABLE posts(
      foo int NOT NULL DEFAULT nextval( 'foo_seq'::regclass )

connection = ActiveRecord::Base.remove_connection

class Post < ActiveRecord::Base
  set_primary_key :foo


  p Post.create
  p Post.primary_key
  ActiveRecord::Base.connection.execute <<_SQL
    DROP TABLE posts;
    DROP SEQUENCE foo_seq;
@SweeD SweeD referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@ttosch ttosch referenced this issue from a commit
@jonleighton jonleighton Fix #3987.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.