Permalink
Browse files

Simplify Postgres query for column_definitions()

column_definitions() needs to fetch the collation for every column, if
present. Previously, it did so using a correlated subquery - a subquery
that references results from the outer scope.

This patch updates the query to remove the subquery in favor of a
simpler and more efficient JOIN clause.

Running the two queries through EXPLAIN against Postgres additionally
shows that the original form with a correlated subquery requires a
Nested Loop Left Join, while the new form with a simple JOIN can use a
more efficient Merge Left Join.
  • Loading branch information...
jordanlewis committed Jan 19, 2017
1 parent d565143 commit f9c6cbd55c56de7994b74630acd141c324411719
Showing with 5 additions and 5 deletions.
  1. +5 −5 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -759,11 +759,11 @@ def column_definitions(table_name)
query(<<-end_sql, "SCHEMA")
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
(SELECT c.collname FROM pg_collation c, pg_type t
WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation),
col_description(a.attrelid, a.attnum) AS comment
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
c.collname, col_description(a.attrelid, a.attnum) AS comment
FROM pg_attribute a
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
LEFT JOIN pg_type t ON a.atttypid = t.oid
LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum

0 comments on commit f9c6cbd

Please sign in to comment.