rails/rails — pull request #17342 by claudiob (2014-10-21 00:53:04+00:00)
Title: Memoize table_structure to save one SQL request

Every time a SQLite3 table is accessed by a Rails app for the first time, the following SQL requests occur:

```
Started GET "/comment_threads/" for 127.0.0.1 at 2014-10-20 17:27:51 -0700
Processing by CommentThreadsController#index as HTML
CommentThread Load (0.9ms) SELECT "comment_threads".* FROM "comment_threads"
SCHEMA (0.1ms) PRAGMA table_info("comment_threads")
SCHEMA (0.1ms) SELECT name FROM sqlite_master WHERE (type = 'table' OR type = 'view') AND NOT name = 'sqlite_sequence'
SCHEMA (0.0ms) PRAGMA table_info("comment_threads")
```

This commit stores the result of the first `PRAGMA table_info` request, so it does not have to be executed again, hence reducing the number of SQL requests.

---

More details on this PR: the reason for the two `PRAGMA` requests is that `find_by_sql`:

* [first calls `columns_hash`](https://github.com/rails/rails/blob/f1e189410124acc5cd3c84c6b3d992ae3f00c962/activerecord/lib/active_record/querying.rb#L41) which invokes `table_structure` to get the list of columns
* [then calls `instantiate`](https://github.com/rails/rails/blob/f1e189410124acc5cd3c84c6b3d992ae3f00c962/activerecord/lib/active_record/querying.rb#L50) which sets the attributes, [including `primary_key`](https://github.com/rails/rails/blob/f1e189410124acc5cd3c84c6b3d992ae3f00c962/activerecord/lib/active_record/attribute_methods/primary_key.rb#L73) which [invokes `table_structure`](https://github.com/rails/rails/blob/f1e189410124acc5cd3c84c6b3d992ae3f00c962/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb#L433) to get the name of the primary-key column

In order to see the output I reported above (with the two `PRAGMA`) you have to temporarily remove `SCHEMA` from `IGNORE_PAYLOAD_NAMES` [in this line](https://github.com/rails/rails/blob/f1e189410124acc5cd3c84c6b3d992ae3f00c962/activerecord/lib/active_record/log_subscriber.rb#L3) since `PRAGMA` lines are not displayed by default in the log file.

This commit is a very small optimization (a `PRAGMA` never takes a long time), but I think it might still be worth, since it removes a SQL request.