2010-11-05 7 views
15

J'ai un problème avec les procédures stockées et la base de données de test dans Rails 3.0.7. Lors de l'exécutionComment migrer des procédures stockées pour tester db?

rake db: Test: préparer

il migre les tables db de schema.rb et non de migrations directement. Les procédures sont créées dans les migrations en appelant la méthode execute et en transmettant une chaîne SQL telle que CREATE FUNCTION foo() ... BEGIN ... END;.

Ainsi, après des recherches, je trouve que vous devez utiliser

config.active_record.schema_format =: sql

intérieur application.rb. Après avoir ajouté cette ligne, j'exécutais

rake db: structure: vidage rake db: test: clone_structure

Le premier est censé vider la structure dans un fichier development.sql et le second crée la base de données de test de ce fichier. Mais mes procédures stockées, et les fonctions n'apparaissent toujours pas dans le db de test. Si quelqu'un sait quelque chose à propos de ce problème. L'aide sera appréciée.

J'ai également essayé d'exécuter rake db: test: préparer encore, mais toujours aucun résultat. MySQL 5.5, Rails 3.0.7, Ruby 1.7.7.

Merci d'avance!

+0

Je voudrais savoir ça aussi !!! –

+1

Ne sait pas si c'est ce dont vous avez besoin, mais vous pouvez utiliser la table ** information_schema.routines ** pour vider vos fonctions et procédures. – rMX

+1

Vous pouvez utiliser mysql.proc et information_schema.triggers comme ma réponse le signale. – RolandoMySQLDBA

Répondre

0

cherchait comment faire la même chose alors vu ceci: http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps

Pour citer:

« db/schema.rb ne peut pas exprimer la base de données des éléments spécifiques tels que les clés étrangères, les déclencheurs ou des procédures stockées Alors que dans une migration, vous pouvez exécuter des instructions SQL personnalisées, le dumper du schéma ne peut pas reconstituer ces instructions à partir de la base de données.Si vous utilisez des fonctionnalités comme celle-ci, vous devez définir le format de schéma sur: sql. "

i.e. .:

config.active_record.schema_format =: sql

Je ne l'ai pas encore essayé moi-même si je vais poster un suivi plus tard.

9

Il n'y a pas d'autre tâche Rake pour cela et structure_dump est défini comme ceci:

# 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 

il fonctionne apparemment que pour les tables, pas de procédures, à moins que vous ne monkey-patch.

La seule solution pour autant que je sache, est d'utiliser shell:

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

Eh bien, hier soir, j'ai eu l'idée suivante: je suis en train d'écraser les tâches rake 'db: schema: dump' et' db: schema: load'. Les nouvelles tâches rake appellent les outils de ligne cmd mysqldump et mysql. Ce n'est pas beau cependant - je m'attends à ce que cette solution soit très fragile en ce qui concerne les futures mises à niveau de rails (la version 3.1 arrive !!!). Il doit y avoir une meilleure solution. –

+1

En fait, je pense que votre solution est beaucoup moins fragile que monkeypatching l'adaptateur. Depuis que j'ai regardé à travers les sources de rake et n'ai trouvé aucun vidage de procédure, il semble que ce soit le seul moyen. Si vous n'aimez pas l'idée de changer la tâche de rake, vous pouvez toujours créer la vôtre, par ex. db: test: clone_via_mysql. –

1

DISCLAIMER: Je ne suis pas Ruby-on-Rails programmeur

strictement en termes de MySQL, vous avez deux des moyens pour extraire des procédures stockées (SP) et les fonctions stockées (SF).

Gardez à l'esprit que mysql.proc et information_schema.routines fournissent le boîtier sur le disque et en mémoire pour SPs. Pourtant, il y a 2 instructions SQL pour les récupérer: SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION.

La première consiste à recueillir tous les PS et en utilisant mysql.proc et FS les former dans les instructions SQL qui les exposent.

Exemple I ont 6 et 2 SPs dans ma base de données FS de test. Voici comment générer SQL pour les 8 routines:

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) 

Vous pouvez faire défiler et recueillir le code nécessaire pour chaque procédure stockée et la fonction.

Déclencheurs doivent être collectés séparément.

5.x MySQL vous pouvez gagner des déclencheurs à l'aide de cette requête:

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 | 
+--------------------------------------------------+ 

ou pour gagner du temps UNION les deux instructions 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 deuxième façon est le meilleur moyen pour CBM, en utilisant mysqldump.

Cela va collecter toutes les structures de tables, SP, SF et triggers dans un seul fichier.

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

Cela fera la même chose, mais sans les trucs CREATE TABLE:

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

Donnez ces essayer !!!

0

Je pris la méthode de Matthew basse d'enlever tâche de râteau existante et redéfinie une tâche à l'aide mysqldump avec les options RolandoMySQLDBA fournies

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 vous voulez Ruby dépotoirs (par opposition à SQL décharges) vous pourriez donner ce petit bijou essayer:

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

Il prend en charge décharge Les triggers et les fonctions pour mysql out of the box sans introduire de nouvelles tâches. Il est basé sur le plugin trigger_happy de tenderlove.

0

Il semblerait que (je n'ai pas testé) rake db:structure:dump la prise en charge des fonctions stockées et des procédures a été ajoutée dans Rails 5. Voir this commit in the rails GitHub project. Le drapeau --routines à mysqldump est décrit here.Notez la méthode structure_dump semble très différente que lorsque Jan Minárik a répondu il y a six ans.

0

On Rails 4 J'accroché dans un crochet poste de charge sur la tâche de coupe db:test:load comme suit:

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']) 

Cette approche fonctionnera automatiquement si vous ne disposez pas de recharger manuellement la db chaque essai et cela n'affectera que la tâche db:test:load, donc je pense que c'est assez isolé. IMHO un peu moche ayant les identifiants de migration dans la tâche, de sorte que vous pouvez alternativement extraire le code de migration à un lib et l'appeler à la fois la migration et la tâche Rake ci-dessus pour le nettoyer.

Questions connexes