2010-11-05 11 views
15

Tengo un problema con los procedimientos almacenados y la base de datos de prueba en Rails 3.0.7. Cuando se ejecuta¿Cómo migrar los procedimientos almacenados para probar db?

rake db: test: preparar

migra las tablas de datos de schema.rb y no de migraciones directamente. Los procedimientos se crean dentro de las migraciones llamando al método de ejecución y pasando una cadena SQL como CREATE FUNCTION foo() ... BEGIN ... END;.

Así que después de investigar, encontré que se debe utilizar

config.active_record.schema_format =: sql

dentro application.rb. Después de añadir esta línea, ejecuté

rake db: Estructura: volcar rake db: test: clone_structure

El primero de ellos se supone que volcar la estructura en un archivo development.sql y crea el segundo la base de datos de prueba de este archivo. Pero mis procedimientos almacenados y funciones todavía no aparecen en la prueba db. Si alguien sabe algo sobre este tema Ayuda será apreciada.

También intenté ejecutar rake db: test: prepare de nuevo, pero todavía no hay resultados.

MySQL 5.5, Rails 3.0.7, Ruby 1.8.7.

¡Gracias de antemano!

+0

¡Me gustaría saberlo también! –

+1

No sé si esto es lo que necesita, pero puede usar la tabla ** information_schema.routines ** para volcar sus funciones y procedimientos. – rMX

+1

Puede usar mysql.proc y information_schema.triggers como mi respuesta lo señala. – RolandoMySQLDBA

Respuesta

0

estaba buscando la manera de hacer la misma cosa entonces vio esto: http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps

Para citar:

"db/schema.rb no puede expresar los elementos específicos de bases de datos tales como restricciones de clave externa, disparadores o procedimientos almacenados Mientras que en una migración puede ejecutar sentencias SQL personalizadas, el volcador de esquemas no puede reconstituir esas declaraciones de la base de datos. Si está utilizando características como esta, entonces debe establecer el formato de esquema en: sql. "

es decir .:

config.active_record.schema_format =: sql

no he probado todavía a mí mismo, así que voy a publicar un seguimiento posterior.

9

No hay otra tarea rastrillo para eso y structure_dump se define así:

# File activerecord/lib/active_record/connection_adapters/mysql_adapter.rb, line 354 
    def structure_dump #:nodoc: 
    if supports_views? 
     sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'" 
    else 
     sql = "SHOW TABLES" 
    end 

    select_all(sql).map do |table| 
     table.delete('Table_type') 
     select_one("SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}")["Create Table"] + ";\n\n" 
    end.join("") 
    end 

por lo que al parecer sólo funciona para las tablas, no a los procedimientos, a menos que se monkeypatch.

La única solución por lo que yo sé es el uso de la cáscara:

mysqldump -R -u <user> <development_database> | mysql -u <user> <test_database> 
+0

Bueno, ayer por la noche tuve la siguiente idea: estoy sobrescribiendo las tareas de rake 'db: schema: dump' y' db: schema: load'. Las nuevas tareas de rake están llamando a las herramientas de línea 'mysqldump' y' mysql' cmd. Sin embargo, esto no es hermoso. Espero que esta solución sea muy frágil en lo que respecta a futuras actualizaciones de rieles (¡ya viene la versión 3.1!). Tiene que haber una mejor solución. –

+1

En realidad, creo que su solución es mucho menos frágil que monopatching el adaptador. Desde que miré a través de las fuentes de rake y no encontré ningún volcado de procedimiento, parece que es la única manera también. Si no le gusta la idea de cambiar la tarea de rake, siempre puede hacer la suya propia, p. db: prueba: clone_via_mysql. –

1

Exención de responsabilidad: No soy un Rubí-on-Rails programador

estrictamente en términos de MySQL, que básicamente tienen dos formas de extraer procedimientos almacenados (SP) y funciones almacenadas (SF).

Tenga en cuenta que mysql.proc y information_schema.routines proporcionan la carcasa en el disco y en la memoria para los SP. Sin embargo, hay 2 declaraciones SQL para recuperarlas: SHOW CREATE PROCEDURE y SHOW CREATE FUNCTION.

La primera forma consiste en recopilar todos los SP y SF utilizando mysql.proc y formarlos en sentencias de SQL que los expongan.

Ejemplo Tengo 6 SP y 2 SF en mi base de datos de prueba. Aquí es cómo generar SQL para los 8 rutinas:

mysql> SELECT CONCAT('SHOW CREATE ',type,' `',db,'`.`',name,'`\\G') SQLStatements FROM mysql.proc; 
+-----------------------------------------------------+ 
| SQLStatements          | 
+-----------------------------------------------------+ 
| SHOW CREATE PROCEDURE `test`.`CreateSampleTable`\G | 
| SHOW CREATE PROCEDURE `test`.`CreateSampleTables`\G | 
| SHOW CREATE PROCEDURE `test`.`GetMissingIntegers`\G | 
| SHOW CREATE FUNCTION `test`.`GetTestTableCounts`\G | 
| SHOW CREATE PROCEDURE `test`.`ImportWeeklyBatch`\G | 
| SHOW CREATE FUNCTION `test`.`InsertName`\G   | 
| SHOW CREATE PROCEDURE `test`.`LoadSampleTables`\G | 
| SHOW CREATE PROCEDURE `test`.`MigrateColumn`\G  | 
+-----------------------------------------------------+ 
8 rows in set (0.00 sec) 

Puede desplazarse a través y recoger el código necesario para cada procedimiento y función almacenada.

Los disparadores se deben recoger por separado.

En MySQL 5.x puede obtener desencadenantes utilizando esta consulta:

mysql> SELECT CONCAT('SHOW CREATE TRIGGER `',trigger_schema,'`.`',trigger_name,'`\\G') SQLStatements FROM information_schema.triggers; 
+--------------------------------------------------+ 
| SQLStatements         | 
+--------------------------------------------------+ 
| SHOW CREATE TRIGGER `test`.`AddPermTempKey`\G | 
| SHOW CREATE TRIGGER `test`.`DeletePermTempKey`\G | 
+--------------------------------------------------+ 

o para ahorrar tiempo UNIÓN las dos sentencias SQL

mysql> SELECT CONCAT('SHOW CREATE ',type,' `',db,'`.`',name,'`\\G') SQLStatements FROM mysql.proc UNION SELECT CONCAT('SHOW CREATE TRIGGER `',trigger_schema,'`.`',trigger_name,'`\\G') SQLStatements FROM information_schema.triggers; 
+-----------------------------------------------------+ 
| SQLStatements          | 
+-----------------------------------------------------+ 
| SHOW CREATE PROCEDURE `test`.`CreateSampleTable`\G | 
| SHOW CREATE PROCEDURE `test`.`CreateSampleTables`\G | 
| SHOW CREATE PROCEDURE `test`.`GetMissingIntegers`\G | 
| SHOW CREATE FUNCTION `test`.`GetTestTableCounts`\G | 
| SHOW CREATE PROCEDURE `test`.`ImportWeeklyBatch`\G | 
| SHOW CREATE FUNCTION `test`.`InsertName`\G   | 
| SHOW CREATE PROCEDURE `test`.`LoadSampleTables`\G | 
| SHOW CREATE PROCEDURE `test`.`MigrateColumn`\G  | 
| SHOW CREATE TRIGGER `test`.`AddPermTempKey`\G  | 
| SHOW CREATE TRIGGER `test`.`DeletePermTempKey`\G | 
+-----------------------------------------------------+ 
10 rows in set (0.07 sec) 

La segunda forma es la forma preferida para los administradores de bases, usando mysqldump.

Esto recogerá todas las estructuras de tablas, SP, SF y desencadenantes en un solo archivo.

mysqldump -h... -u... -p... --no-data --routines --triggers --all-databases > MySQLSchema.sql 

Esto hará lo mismo pero sin el material CREATE TABLE:

mysqldump -h... -u... -p... --no-data --no-create-info --routines --triggers --all-databases > MySQLSchema.sql 

dar a estos a Try !!!

0

Tomé método de eliminación de tarea rastrillo existente de Matthew Bass y redefinió una tarea usando mysqldump con las opciones que RolandoMySQLDBA proporcionado

http://matthewbass.com/2007/03/07/overriding-existing-rake-tasks/

Rake::TaskManager.class_eval do 
    def remove_task(task_name) 
    @tasks.delete(task_name.to_s) 
    end 
end 

def remove_task(task_name) 
    Rake.application.remove_task(task_name) 
end 

# Override existing test task to prevent integrations 
# from being run unless specifically asked for 
remove_task 'db:test:prepare' 

namespace :db do 
    namespace :test do 
    desc "Create a db/schema.rb file" 
    task :prepare => :environment do 
     sh "mysqldump --routines --no-data -u root ni | mysql -u root ni_test" 
    end 
    end 
end 
0

Si desea Rubí vertederos (en contraposición a SQL vertederos) es posible dar a esta joya una oportunidad:

https://github.com/jovoto-team/trackless_triggers

soporta volcado Desencadenadores y funciones para mysql listos para usar sin introducir nuevas tareas de rake. Se basa en el complemento trigger_happy de tenderlove.

0

Parece (no lo he probado) rake db:structure:dump Se ha agregado soporte para funciones y procedimientos almacenados en Rails 5. Consulte this commit in the rails GitHub project. La bandera --routines a mysqldump se describe here.El método de nota structure_dump parece muy diferente de cuando Jan Minárik respondió hace seis años.

0

En Los Carriles 4 Me enganchó en un gancho de carga posterior en la tarea db:test:load rastrillo de la siguiente manera:

require File.expand_path('../config/application', __FILE__) 

Rails.application.load_tasks 

namespace :db do 
    namespace :test do 

    task :post_load_hook do 
     re_create_sps 
    end 

    def re_create_sps 
     [20170905123456, 20170905123457].each do |version| 
     ActiveRecord::Migrator.run(
      :down, ActiveRecord::Migrator.migrations_paths, version) 
     ActiveRecord::Migrator.run(
      :up, ActiveRecord::Migrator.migrations_paths, version) 
     end 
    end 

    # stored procs must be restored each time. 
    end 
end 

Rake::Task['db:test:load'].enhance(['db:test:post_load_hook']) 

Este enfoque se ejecutará automáticamente para que no tenga que recargar manualmente la base de datos de cada prueba y solo afectará a la tarea db:test:load, por lo que creo que está bastante aislada.

En mi humilde opinión es un poco feo tener los identificadores de migración en la tarea, por lo que alternativamente puede extraer el código de migración a una lib y llamarlo desde la migración y la tarea de Rake anterior para limpiarlo.

Cuestiones relacionadas