diff options
author | Xavier Noria <fxn@hashref.com> | 2011-11-25 14:29:34 -0800 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2011-11-25 14:29:34 -0800 |
commit | 1be9830d4d99e2bf56f1cadf74b843f22d66da35 (patch) | |
tree | f4acc78649b273bc1bf97fe4bb70e3ca9167ffbf | |
parent | a5b362df567ed4a0167a83e9b8f00b9f614ac38b (diff) | |
download | rails-1be9830d4d99e2bf56f1cadf74b843f22d66da35.tar.gz rails-1be9830d4d99e2bf56f1cadf74b843f22d66da35.tar.bz2 rails-1be9830d4d99e2bf56f1cadf74b843f22d66da35.zip |
add the query to AR::Relation#explain output
Rationale: this is more readable if serveral queries
are involved in one call. Also, it will be possible
to let AR log EXPLAINs automatically in production
mode, where queries are not even around.
5 files changed, 17 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index f0891440a6..0c32ad5139 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'active_support/core_ext/object/blank' require 'active_support/core_ext/module/delegation' @@ -155,8 +156,8 @@ module ActiveRecord end queries.map do |sql| - @klass.connection.explain(sql) - end.join + "EXPLAIN for: #{sql}\n#{@klass.connection.explain(sql)}" + end.join("\n") end def to_a diff --git a/activerecord/test/cases/adapters/mysql2/explain_test.rb b/activerecord/test/cases/adapters/mysql2/explain_test.rb index 8ea777b72b..68ed361aeb 100644 --- a/activerecord/test/cases/adapters/mysql2/explain_test.rb +++ b/activerecord/test/cases/adapters/mysql2/explain_test.rb @@ -9,12 +9,15 @@ module ActiveRecord def test_explain_for_one_query explain = Developer.where(:id => 1).explain + assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain assert_match %(developers | const), explain end def test_explain_with_eager_loading explain = Developer.where(:id => 1).includes(:audit_logs).explain + assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain assert_match %(developers | const), explain + assert_match %(EXPLAIN for: SELECT `audit_logs`.* FROM `audit_logs` WHERE `audit_logs`.`developer_id` IN (1)), explain assert_match %(audit_logs | ALL), explain end end diff --git a/activerecord/test/cases/adapters/postgresql/explain_test.rb b/activerecord/test/cases/adapters/postgresql/explain_test.rb index 0d599ed37f..0b61f61572 100644 --- a/activerecord/test/cases/adapters/postgresql/explain_test.rb +++ b/activerecord/test/cases/adapters/postgresql/explain_test.rb @@ -9,6 +9,7 @@ module ActiveRecord def test_explain_for_one_query explain = Developer.where(:id => 1).explain + assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain assert_match %(QUERY PLAN), explain assert_match %(Index Scan using developers_pkey on developers), explain end @@ -16,7 +17,9 @@ module ActiveRecord def test_explain_with_eager_loading explain = Developer.where(:id => 1).includes(:audit_logs).explain assert_match %(QUERY PLAN), explain + assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain assert_match %(Index Scan using developers_pkey on developers), explain + assert_match %(EXPLAIN for: SELECT "audit_logs".* FROM "audit_logs" WHERE "audit_logs"."developer_id" IN (1)), explain assert_match %(Seq Scan on audit_logs), explain end end diff --git a/activerecord/test/cases/adapters/sqlite3/explain_test.rb b/activerecord/test/cases/adapters/sqlite3/explain_test.rb index e18892821d..b227bce680 100644 --- a/activerecord/test/cases/adapters/sqlite3/explain_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/explain_test.rb @@ -9,12 +9,15 @@ module ActiveRecord def test_explain_for_one_query explain = Developer.where(:id => 1).explain + assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain assert_match(/(SEARCH )?TABLE developers USING (INTEGER )?PRIMARY KEY/, explain) end def test_explain_with_eager_loading explain = Developer.where(:id => 1).includes(:audit_logs).explain + assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain assert_match(/(SEARCH )?TABLE developers USING (INTEGER )?PRIMARY KEY/, explain) + assert_match %(EXPLAIN for: SELECT "audit_logs".* FROM "audit_logs" WHERE "audit_logs"."developer_id" IN (1)), explain assert_match(/(SCAN )?TABLE audit_logs/, explain) end end diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index ad12dca7e8..0f1f6eba4c 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -1287,6 +1287,7 @@ User.where(:id => 1).joins(:posts).explain may yield <plain> +EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `posts` ON `posts`.`user_id` = `users`.`id` WHERE `users`.`id` = 1 <plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------------<plus> | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | <plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------------<plus> @@ -1302,6 +1303,7 @@ Active Record performs a pretty printing that emulates the one of the database shells. So, the same query running with the PostgreSQL adapter would yield instead <plain> +EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE "users"."id" = 1 QUERY PLAN ------------------------------------------------------------------------------ Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0) @@ -1324,12 +1326,15 @@ User.where(:id => 1).includes(:posts).explain yields <plain> +EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 <plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus> | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | <plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus> | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | | <plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus> 1 row in set (0.00 sec) + +EXPLAIN for: SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` IN (1) <plus>----<plus>-------------<plus>-------<plus>------<plus>---------------<plus>------<plus>---------<plus>------<plus>------<plus>-------------<plus> | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | <plus>----<plus>-------------<plus>-------<plus>------<plus>---------------<plus>------<plus>---------<plus>------<plus>------<plus>-------------<plus> |