Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Column definitions not cached for calculations on has_many association with :include

#4991

While trying out Rails 3 for one of my applications, I have been bitten by the following.

When doing a calculation such as .count on has_many associations that use :include => some_model, it appears column definitions are not cached. It's not cached when config.cache_classes = true, or even in the same request. This causes pretty serious performance issues, because retrieving column definitions this often is expensive.

A short example:

class Article < ActiveRecord::Base
 has_many :comments, :include => :author
end

class Comment < ActiveRecord::Base
 belongs_to :author
end

class Author < ActiveRecord::Base
end

Article.last.comments.count # Retrieves column definitions from db every single time.

Attached is a patch with a failing test. I don't know if there are other kinds of queries that suffer from the same problem.

Reported by Rolf Timmermans · June 28th, 2010 @ 06:39 AM

State: resolved
Milestone: 3.0.5
Assigned to: Emilio Tagua Emilio Tagua
Importance: Medium

Activity

  1. Rolf Timmermans
    Rolf Timmermans

    It appears the problem also occurs with a simple call to .joins() in combination with has_many associations:

    Article.joins(:comments).first # Retrieves column definitions from db every single time.

    I have updated the patch with a second failing test for this case.

    June 28th, 2010 @ 08:03 AM

  2. Michael Koziarski
    Michael Koziarski
    • Assigned user set to Emilio Tagua
    • Milestone cleared.
    • Importance changed from to Medium

    I had a quick look at this but couldn't see anything obviously broken. Assigning to emilio to take a look

    June 29th, 2010 @ 04:48 AM

  3. Emilio Tagua
    Emilio Tagua
    • State changed from new to invalid

    Hey Rolf,

    I don't think column information is being reload from database, those test just ask if columns method is invoked, which it is but the db is never queried again for column information, in fact these tests will pass (already tried):

      def test_calculations_on_has_many_association_with_include_should_not_reload_column_definitions
        assert_queries 2 do
          Author.last.posts_with_comments.count
        end
        assert_queries 2 do
          Author.last.posts_with_comments.count
        end
      end
    
      def test_joins_on_has_many_associations_should_not_reload_column_definitions
        assert_queries 1 do
          Author.joins(:posts).first
        end
        assert_queries 1 do
          Author.joins(:posts).first
        end
      end
    

    The method is called but being loaded from cache, not db. I'm marking the ticket as invalid but maybe i'm missing something, if so please feel free to keep commenting this and re open the ticket.

    Thanks!

    June 29th, 2010 @ 02:31 PM

  4. Rolf Timmermans
    Rolf Timmermans

    Hi Emilio,

    Thank you for your answer. I was using the PostgreSQL adapter in my original application. If you try it in a real application, you'll see in the Rails log that all queries are being executed in succession, no caching is applied in the cases I mentioned.

    I'm looking at the source of ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#columns, and I can't find any caching strategy being used. The #columns method calls #column_definitions directly, which calls the #query method, which executes a db query on the underlying pg library.

    I'm also pretty sure that assert_queries does not count the queries that are executed directly from the database adapter this way. In the test helper of ActiveRecord I can see that the connection's #execute method is overridden, but not #query.

    For MySQL however, the call to MySQLAdapter#columns does use #execute internally. But note that in the definition of execute_with_query_record (in activerecord/test/cases/helper.rb, which overrides the #execute method to store all executed queries for testing purposes), a check is made to see if the query should be ignored! The definition of IGNORED_SQL there specifically includes /SHOW FIELDS/.

    Finally, for SQLite3, the call to SQLite3Adapter#columns calls #table_structure directly on the sqlite library, which also has no caching strategy and which also does not pass through the filter of assert_queries (it bypasses #execute on the connection adapter).

    Please, let me know how I can adjust the test cases to make them clearer. The call to #columns is the only place in the connection adapter interface I could find that is shared between all adapters. In all three cases I tried (MySQL, PostgreSQL and SQLite3) I have been able to verify that there is 1) no caching strategy in the adapter and 2) the query is not caught by assert_queries. Should assert_queries be adjusted? Does the connection adapter even need to implement the caching, or should it be done in a higher abstraction level? I'm definitely willing to assist in solving this problem, but currently I can't seem to pinpoint exactly where the column definition caching is done right now (or should be done).

    June 29th, 2010 @ 03:26 PM

  5. Rolf Timmermans
    Rolf Timmermans

    Also, note that calling .count on an association without :include does properly use cached column definitions. The first of the tests below succeeds, the second fails. What is the difference in implementation?

    def test_calculations_on_has_many_association_should_not_reload_column_definitions
      Author.last.posts.count
      Author.connection.expects(:columns).never
      Author.last.posts.count
    end
    
    def test_calculations_on_has_many_association_with_include_should_not_reload_column_definitions
      Author.last.posts_with_comments.count
      Author.connection.expects(:columns).never
      Author.last.posts_with_comments.count
    end
    

    June 29th, 2010 @ 09:17 PM

  6. Emilio Tagua
    Emilio Tagua

    Rolf,

    I tried running this test on MySQL, PostgreSQL and Sqlite3:

    
      def test_calculations_on_has_many_association_with_include_should_not_reload_column_definitions
        logger = ActiveRecord::Base.logger
        logger.warn("STARTS first count")
        assert_queries 2 do
          Author.last.posts_with_comments.count
        end
        logger.warn("ENDS first count")
        logger.warn("STARTS second count")
        assert_queries 2 do
          Author.last.posts_with_comments.count
        end
        logger.warn("ENDS second count")
      end
    

    On PostgreSQL. The test passed, and the output on debug.log was:

    STARTS first count
      Author Load (0.6ms)  SELECT "authors".* FROM "authors" ORDER BY authors.id DESC LIMIT 1
      SQL (0.8ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (1.1ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.8ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.7ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.7ms)  SELECT COUNT(DISTINCT "posts"."id") AS count_id FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE ("posts".author_id = 2)
    ENDS first count
    STARTS second count
      Author Load (0.3ms)  SELECT "authors".* FROM "authors" ORDER BY authors.id DESC LIMIT 1
      SQL (0.7ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.4ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.6ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.4ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.3ms)  SELECT COUNT(DISTINCT "posts"."id") AS count_id FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE ("posts".author_id = 2)
    ENDS second count
    

    On SQLite3, the test also passed and the output was simpler:

    STARTS first count
      Author Load (0.3ms)  SELECT "authors".* FROM "authors" ORDER BY authors.id DESC LIMIT 1
      SQL (0.2ms)  SELECT COUNT(DISTINCT "posts"."id") AS count_id FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE ("posts".author_id = 2)
    ENDS first count
    STARTS second count
      Author Load (0.1ms)  SELECT "authors".* FROM "authors" ORDER BY authors.id DESC LIMIT 1
      SQL (0.2ms)  SELECT COUNT(DISTINCT "posts"."id") AS count_id FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE ("posts".author_id = 2)
    ENDS second count
    

    On MySQL the test passed with debug.log output:

    STARTS first count
      Author Load (0.8ms)  SELECT `authors`.* FROM `authors` ORDER BY authors.id DESC LIMIT 1
      SQL (1.1ms)  SELECT COUNT(DISTINCT `posts`.`id`) AS count_id FROM `posts` LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id` WHERE (`posts`.author_id = 2)
    ENDS first count
    STARTS second count
      Author Load (0.2ms)  SELECT `authors`.* FROM `authors` ORDER BY authors.id DESC LIMIT 1
      SQL (0.6ms)  SELECT COUNT(DISTINCT `posts`.`id`) AS count_id FROM `posts` LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id` WHERE (`posts`.author_id = 2)
    ENDS second count
      SQL (0.2ms)  ROLLBACK
    

    I tried defining IGNORED_SQL as an empty array, SQLite3 and postgreSQL tests were green but MySQL failed with the following test output:

    9 instead of 2 queries were executed.
    Queries:
    SELECT     `authors`.* FROM       `authors`  ORDER BY  authors.id DESC LIMIT 1
    SHOW FIELDS FROM `comments`
    SHOW FIELDS FROM `posts`
    SHOW FIELDS FROM `posts`
    SHOW FIELDS FROM `comments`
    SHOW FIELDS FROM `comments`
    SHOW FIELDS FROM `posts`
    SHOW FIELDS FROM `comments`
    SELECT     COUNT(DISTINCT `posts`.`id`) AS count_id FROM       `posts`  LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id` WHERE     (`posts`.author_id = 2).
    <2> expected but was
    <9>.
    

    I think a problem may be in PostgreSQL, i added a debug line in PostgreSQLAdapter#columns, ran the same test and had the following output:

    STARTS first count
      Author Load (16.3ms)  SELECT "authors".* FROM "authors" ORDER BY authors.id DESC LIMIT 1
    Columns for comments with name comments Columns
      SQL (0.7ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for posts with name posts Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for posts with name posts Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for comments with name comments Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for comments with name comments Columns
      SQL (0.7ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for posts with name posts Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for comments with name comments Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.8ms)  SELECT COUNT(DISTINCT "posts"."id") AS count_id FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE ("posts".author_id = 2)
    ENDS first count
    STARTS second count
      Author Load (0.3ms)  SELECT "authors".* FROM "authors" ORDER BY authors.id DESC LIMIT 1
    Columns for comments with name comments Columns
      SQL (0.7ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for posts with name posts Columns
      SQL (0.6ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for comments with name comments Columns
      SQL (0.6ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for comments with name comments Columns
      SQL (0.6ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for posts with name posts Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"posts"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
    Columns for comments with name comments Columns
      SQL (0.5ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"comments"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum
    
      SQL (0.4ms)  SELECT COUNT(DISTINCT "posts"."id") AS count_id FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE ("posts".author_id = 2)
    ENDS second count
    

    If you try the same on other adapters you will get something like this:

      SQL (0.1ms)  BEGIN
    STARTS first count
      Author Load (0.3ms)  SELECT `authors`.* FROM `authors` ORDER BY authors.id DESC LIMIT 1
    Columns for comments with name comments Columns
    Columns for posts with name posts Columns
    Columns for posts with name posts Columns
    Columns for comments with name comments Columns
    Columns for comments with name comments Columns
    Columns for posts with name posts Columns
    Columns for comments with name comments Columns
      SQL (0.4ms)  SELECT COUNT(DISTINCT `posts`.`id`) AS count_id FROM `posts` LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id` WHERE (`posts`.author_id = 2)
    ENDS first count
    STARTS second count
      Author Load (0.2ms)  SELECT `authors`.* FROM `authors` ORDER BY authors.id DESC LIMIT 1
    Columns for comments with name comments Columns
    Columns for posts with name posts Columns
    Columns for comments with name comments Columns
    Columns for comments with name comments Columns
    Columns for posts with name posts Columns
    Columns for comments with name comments Columns
      SQL (0.3ms)  SELECT COUNT(DISTINCT `posts`.`id`) AS count_id FROM `posts` LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id` WHERE (`posts`.author_id = 2)
    ENDS second count
      SQL (0.1ms)  ROLLBACK
    

    June 30th, 2010 @ 02:50 PM

  7. Rolf Timmermans
    Rolf Timmermans

    Hi Emilio,

    Your results seem consistent with mine insofar I've tried them (will do more tests later). What struck me the first time as well, is that in all cases where column definition caching fails on PostgreSQL, the number of calls to the #columns method on the connection adapter is less on the second call, no matter the adapter. From the output of your final log the columns for comments are loaded 4 times and 3 times for posts, vs. 4x comments and 2x posts (!) after the second query.

    It seems like there is an intention to cache the column definitions before they hit the connection adapter. Do you agree that the second time that an ActiveRecord relation is retrieved, ideally there should be no calls at all to #columns on the connection adapter? If so, I will read some more Rails 3 source code to start working on a patch.

    July 2nd, 2010 @ 02:26 PM

  8. Sam Soffes
    Sam Soffes

    I have been experiencing this issue as well since I upgraded 3.0.0.beta3 to 3.0.0.beta4

    July 23rd, 2010 @ 10:10 PM

  9. Sam Soffes
    Sam Soffes

    Why is this marked as spam? Several people have confirmed that they are experiencing this issue?

    I am still seeing this issue in 3.0.0.rc.

    August 3rd, 2010 @ 04:50 AM

  10. sebastian
    sebastian

    Any news on this so far? I'm having the same problem with postgresql.
    Besides the performance implications, the extra queries really bloat the debug log.

    August 6th, 2010 @ 01:13 AM

  11. Garret Cox
    Garret Cox

    I'm seeing the same issue. In fact, it doesn't seem to have anything to do with :has_many or joins...if a table is queried, the query is immediately followed by this "SELECT a.attname ..." query.

    example:

    Started GET "/" for 127.0.0.1 at 2010-08-07 01:17:06 -0500
      Processing by ItemsController#index as HTML
      Item Load (0.4ms)  SELECT "items".* FROM "items"
      SQL (0.7ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
     FROM pg_attribute a LEFT JOIN pg_attrdef d
     ON a.attrelid = d.adrelid AND a.attnum = d.adnum
     WHERE a.attrelid = '"items"'::regclass
     AND a.attnum > 0 AND NOT a.attisdropped
     ORDER BY a.attnum


    Image Load (2.4ms) SELECT "images".* FROM "images" WHERE (item_id IN (2,3)) ORDER BY "order" ASC SQL (0.8ms) SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum WHERE a.attrelid = '"images"'::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum


    Rendered orders/item_quantity.html.erb (0.6ms) SQL (0.8ms) SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum WHERE a.attrelid = '"users"'::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum User Load (0.5ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 2) LIMIT 1 SQL (0.6ms) SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum WHERE a.attrelid = '"users"'::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum Rendered items/show.html.erb (157.4ms) Rendered orders/item_quantity.html.erb (0.5ms) CACHE (0.0ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 2) LIMIT 1 Rendered items/show.html.erb (6.7ms) CACHE (0.0ms) SELECT "users". FROM "users" WHERE ("users"."id" = 2) LIMIT 1 CACHE (0.0ms) SELECT "users". FROM "users" WHERE ("users"."id" = 2) LIMIT 1 CACHE (0.0ms) SELECT "users". FROM "users" WHERE ("users"."id" = 2) LIMIT 1 CACHE (0.0ms) SELECT "users". FROM "users" WHERE ("users"."id" = 2) LIMIT 1 Rendered items/index.html.erb within layouts/application (170.5ms) Completed 200 OK in 233ms (Views: 171.8ms | ActiveRecord: 6.2ms)

    August 7th, 2010 @ 07:24 AM

  12. Sam Soffes
    Sam Soffes

    I was digging through the commits from 3.0.0.beta3 to 3.0.0.beta4 to try and track down the issue. I didn't see anything that looked like it was causing it, but obviously I missed something.

    The biggest change I noticed was a move to the pg gem. Not sure if that has anything to do with it though.

    August 7th, 2010 @ 03:01 PM

  13. Ryan Bigg
    Ryan Bigg

    Automatic cleanup of spam.

    October 11th, 2010 @ 12:11 PM

  14. Sam Soffes
    Sam Soffes

    This is not spam. It is still a bug in 3.0.0.

    October 11th, 2010 @ 03:57 PM

  15. Ryan Bigg
    Ryan Bigg
    • State changed from invalid to needs-more-info

    Please provide a new patch that applies cleanly to master.

    October 11th, 2010 @ 08:41 PM

  16. Szymon Nowak
  17. Jeremy Kemper
  18. Ryan Bigg
    Ryan Bigg

    Automatic cleanup of spam.

    October 16th, 2010 @ 02:42 AM

  19. Rolf Timmermans
    Rolf Timmermans

    I tested for this behaviour recently with Rails edge. It seems to be solved by the fix to #5392 column_definitions method being called before and after every single SQL stat....

    October 16th, 2010 @ 03:19 PM

  20. Santiago Pastorino
  21. Santiago Pastorino
  22. Emilio Tagua
    Emilio Tagua
    • State changed from needs-more-info to resolved

    Indeed, it looks like it was resolved in #5392 column_definitions method being called before and after every single SQL stat...

    I'm changing it to resolved, if any of you still experience the problem, please re open it.

    Thanks.

    February 25th, 2011 @ 01:53 PM

  23. bingbing