Pretty Print SQL на Ruby

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

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

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

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

Я действительно хочу query.to_sql.pretty_format_sql и увидеть результат получше.

Спасибо.


person Dmytrii Nagirniak    schedule 27.04.2012    source источник
comment
Если вы используете JRuby, вы можете рассмотреть несколько ответов на аналогичный вопрос, заданный для Java, например org.hibernate.jdbc.util.BasicFormatterImpl в Hibernate.   -  person Abe Voelker    schedule 27.04.2012


Ответы (3)


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

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 

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

person mdesantis    schedule 27.04.2012
comment
Он должен работать, но я действительно хочу избежать использования устаревших плагинов rails (не драгоценных камней). - person Dmytrii Nagirniak; 27.04.2012
comment
Я тоже чувствовал, что это не такая уж стандартная библиотека ... но нетрудно извлечь хорошие части и сделать из них жемчужину (я протестировал ее, и она работает очень хорошо, и, увидев, что я не могу найти альтернативы, зачем переписывать рабочие вещи?) ... попробую! - person mdesantis; 27.04.2012

anbt-sql-formatter в первом ответе: доступен как гем, вы можете установить его с помощью:

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
}
person knut    schedule 25.08.2013

Шесть лет спустя есть еще один вариант: https://github.com/kvokka/pp_sql

«Замените стандартный метод ActiveRecord # to_sql гемом anbt-sql-formatter для красивого вывода кода SQL в консоли. Журнал Rails также будет отформатирован».

Использует anbt-sql-formatter под капотом, но делает это поведение по умолчанию для .to_sql

person David Hempy    schedule 07.09.2018