2012-04-27 4 views
13

Есть ли простой способ для довольно печатать случайный SQL в консоли (rails 3)?Pretty Print SQL в Ruby

Нечто похожее на awesome_print, или, может быть, даже Pretty Print.

Невозможно понять все возможные диалекты или быть супер-продвинутыми.
Все, что я действительно хочу, это проще проверить SQL, сгенерированный ActiveRecord.

В настоящее время я просто скопируйте SQL, выйдите в онлайн, чтобы отформатировать его, что, очевидно, является убийцей производительности.

Я действительно хочу query.to_sql.pretty_format_sql и видеть более приятный выход.

Спасибо.

+0

Если вы используете JRuby вы могли бы рассмотреть некоторые ответы на подобный вопрос [] (http://stackoverflow.com/q/312552/215168) позировала для Java, такие как 'org.hibernate в Hibernate. jdbc.util.BasicFormatterImpl' –

+0

Hah, используя МРТ. –

ответ

9

Попробуйте это:

git clone https://github.com/sonota/anbt-sql-formatter 
cd anbt-sql-formatter 
rails setup.rb 

Затем в инициализаторе Rails:

# config/initializers/pretty_format_sql.rb 
class String 
    def pretty_format_sql 
    require "anbt-sql-formatter/formatter" 
    rule = AnbtSql::Rule.new 
    rule.keyword = AnbtSql::Rule::KEYWORD_UPPER_CASE 
    %w(count sum substr date).each{|func_name| 
     rule.function_names << func_name.upcase 
    } 
    rule.indent_string = " " 
    formatter = AnbtSql::Formatter.new(rule) 
    formatter.format(self) 
    end 
end 

Тест:

rails console 
# Some complex SQL 
puts Recipe.joins(:festivity).where(['? BETWEEN festivities.starts_at AND festivities.ends_at', Time.utc(0,Time.now.month,Time.now.day,12,0,0)]).to_sql.pretty_format_sql 
SELECT 
     "recipes" . * 
    FROM 
     "recipes" INNER JOIN "festivities" 
      ON "festivities" . "id" = "recipes" . "festivity_id" 
    WHERE 
     (
      '0000-04-27 12:00:00.000000' BETWEEN festivities.starts_at AND festivities.ends_at 
     ) 
=> nil 

Я оставляю рафинирования вам (рефакторинга: обезьяна-ремонтного -> модуль, индивидуальное форматирование и т. д. :-))

+2

Он должен выполнять эту работу, но я действительно хочу избежать использования устаревших плагинов rails (non gems). –

+0

Я тоже чувствовал, что это не так «стандартная» библиотека ... но не должно быть трудно извлечь хорошие детали и сделать из них драгоценный камень (я тестировал его, и он работает очень хорошо, и, видя, что я не могу найти альтернативы, зачем переписывать рабочие вещи?) ... Я попробую! – mdesantis

7

anbt-sql-formatter из first answer является available as a gem, вы можете установить его с помощью:

gem install anbt-sql-formatter 

Вот пример использования:

require "anbt-sql-formatter/formatter" 
rule = AnbtSql::Rule.new 
    formatter = AnbtSql::Formatter.new(rule) 

[ 
"SELECT `col1`, `col2` FROM `table` WHERE ((`col1` = 1) AND (`col2` = 5))", 
"SELECT `col1`, `col2` FROM `table` WHERE (`col1` = 1) AND (`col2` = 5)", 
"SELECT `col1` FROM `table` WHERE (`col1` IN (SELECT * FROM `table21` WHERE (`col2` = 5)))", 
"SELECT `col1` FROM `table` INNER JOIN `tab2` ON (`tab1`.`id` = `tab2`.`id1`) WHERE ((`id` >= 1) AND (`id` <= 5))", 
].each{|sql_cmd| 
    puts "======" 
    puts sql_cmd 
    puts formatter.format(sql_cmd) 
} 

Результат:

====== 
SELECT `col1`, `col2` FROM `table` WHERE ((`col1` = 1) AND (`col2` = 5)) 
SELECT 
     `col1` 
     ,`col2` 
    FROM 
     `table` 
    WHERE 
     (
      (
       `col1` = 1 
      ) 
      AND (
       `col2` = 5 
      ) 
     ) 
====== 
SELECT `col1`, `col2` FROM `table` WHERE (`col1` = 1) AND (`col2` = 5) 
SELECT 
     `col1` 
     ,`col2` 
    FROM 
     `table` 
    WHERE 
     (
      `col1` = 1 
     ) 
     AND (
      `col2` = 5 
     ) 
====== 
SELECT `col1` FROM `table` WHERE (`col1` IN (SELECT * FROM `table21` WHERE (`col2` = 5))) 
SELECT 
     `col1` 
    FROM 
     `table` 
    WHERE 
     (
      `col1` IN (
       SELECT 
         * 
        FROM 
         `table21` 
        WHERE 
         (
          `col2` = 5 
         ) 
      ) 
     ) 
====== 
SELECT `col1` FROM `table` INNER JOIN `tab2` ON (`tab1`.`id` = `tab2`.`id1`) WHERE ((`id` >= 1) AND (`id` <= 5)) 
SELECT 
     `col1` 
    FROM 
     `table` INNER JOIN `tab2` 
      ON (
      `tab1`.`id` = `tab2`.`id1` 
     ) 
    WHERE 
     (
      (
       `id` >= 1 
      ) 
      AND (
       `id` <= 5 
      ) 
     ) 

Существует также возможность расширения правил, например

# User defined additional functions: 
%w(count sum substr date coalesce).each{|func_name| 
    rule.function_names << func_name.upcase 
}