2012-04-27 13 views
13

¿Hay una manera fácil de imprimir bonito SQL aleatorio en la consola (carriles 3)?Pretty Print SQL en Ruby

Algo similar a awesome_print, o tal vez incluso Pretty Print.

No tiene que entender todos los dialectos posibles o ser súper avanzado.
Todo lo que realmente quiero es inspeccionar el SQL generado por ActiveRecord más fácil.

Actualmente solo copie el SQL en línea para formatearlo, que obviamente es un asesino de productividad.

Realmente quiero query.to_sql.pretty_format_sql y veo la mejor salida.

Gracias.

+0

Si está usando JRuby usted podría considerar algunas respuestas para una [pregunta similar] (http://stackoverflow.com/q/312552/215168) posaron para Java, como por ejemplo 'org.hibernate de Hibernate. jdbc.util.BasicFormatterImpl' –

+0

Hah, usando MRI. –

Respuesta

9

Prueba esto:

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

Luego, en un inicializador de rieles:

# 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 

prueba:

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 

dejo refinar a usted (refactorización: mono-parcheo -> módulo, formateo personalizado, etc. :-))

+2

Debería hacer el trabajo, pero realmente quiero evitar el uso de complementos de rieles en desuso (no gemas). –

+0

También sentí que no es una versión "estándar" ... pero no debería ser difícil extraer las partes buenas y hacer de ellas una joya (lo probé y funciona bastante bien, y al ver que no podía encuentra alternativas, ¿por qué reescribir cosas que funcionan?) ... ¡Lo intentaré! – mdesantis

7

El anbt-sql-formatter del first answer es available as a gem, puede instalarlo con:

gem install anbt-sql-formatter 

Aquí un ejemplo del uso:

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) 
} 

El resultado:

====== 
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 
      ) 
     ) 

También existe la posibilidad de ampliar las reglas, por ejemplo

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