2010-11-05 213 views
15

我在Rails 3.0.7中遇到了存储过程和测试数据库的问题。当运行如何将存储过程迁移到测试数据库?

耙分贝:测试:准备

它迁移从schema.rb,而不是直接从迁移的数据库表。这些过程通过调用execute方法并传入SQL字符串(如CREATE FUNCTION foo() ... BEGIN ... END;)在迁移中创建。

所以研究后,我发现,你应该使用

config.active_record.schema_format =:SQL

application.rb。增加这样之后,我执行

耙分贝:结构:转储 耙分贝:测试:clone_structure

第一个应该转储结构成development.sql文件,第二个创造来自这个文件的测试数据库。但是我的存储过程和函数仍然没有出现在测试数据库中。如果有人对这个问题有所了解。 帮助将不胜感激。

我也尝试运行rake db:test:再次准备,但仍然没有结果。

MySQL 5.5,Rails 3.0.7,Ruby 1.8.7。

在此先感谢!

+0

我也想知道这个! – 2011-05-06 19:15:27

+1

不知道这是否是你需要的,但是你可以使用table ** information_schema.routines **来转储你的函数和过程。 – rMX 2011-05-11 04:03:56

+1

你可以使用mysql.proc和information_schema.triggers作为我的答案。 – RolandoMySQLDBA 2011-05-12 18:44:09

回答

0

正在寻找如何做同样的事情,然后看到这个:http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps

引述:

“DB/schema.rb无法表达数据库的特定项目,如外键约束,触发器或存储过程。在迁移过程中,您可以执行自定义SQL语句,但模式转储程序无法从数据库中重新组合这些语句。如果您使用的功能如此,则应该将模式格式设置为:sql。“

即:

config.active_record.schema_format =:SQL

我还没有尝试过自己,但这样我将在后面张贴跟进。

9

没有为没有其他rake任务和structure_dump的定义是这样的:

# 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 

所以它显然仅适用于表,而不是程序,除非你猴补丁吧。

,据我所知道的唯一的解决方案是使用shell:

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

那么,昨天晚上我有以下想法:我覆盖了rake任务'db:schema:dump'和'db:schema:load'。新的rake任务正在调用'mysqldump'和'mysql' cmd行工具。然而,这并不美观 - 我期望这个解决方案对于未来的Rails升级(3.1版即将发布!!!)非常脆弱。必须有更好的解决方案。 – 2011-05-07 10:24:33

+1

实际上我认为你的解决方案远不如monkeypatching适配器脆弱。由于我查看了rake源代码并没有发现任何程序转储,它看起来也是唯一的方法。如果你不喜欢改变耙子任务的想法,你总是可以自己制作耙子任务。 DB:测试:clone_via_mysql。 – 2011-05-10 07:26:04

1

免责声明:我不是的Ruby-on-Rails的程序员

严格在MySQL方面,你基本上有两种提取存储过程(SP)和存储函数(SF)的方法。

请记住,mysql.proc和information_schema.routines为SP提供磁盘和内存中的外壳。但是,有2条SQL语句可以检索它们:SHOW CREATE PROCEDURESHOW CREATE FUNCTION

第一种方法是使用mysql.proc收集所有的SP和SF,并将它们形成SQL语句以公开它们。

示例我的测试数据库中有6个SP和2个SF。以下是如何为所有8个例程生成SQL:

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) 

您可以遍历并收集每个存储过程和函数所需的代码。

触发器必须单独收集。

在MySQL 5.x中,您可以收集使用此查询触发器:

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

或节省时间UNION两个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) 

第二种方式是数据库管理员的首选方式,使用mysqldump。

这将收集单个文件中的所有表结构,SP,SF和触发器。

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

这也将这样做,但没有CREATE TABLE的东西:

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

给这些一个Try!

0

我把消除现有rake任务的马修·巴斯的方法和使用mysqldump与如果你想红宝石转储是RolandoMySQLDBA提供

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

的选项重新定义任务(相对于SQL转储)

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

它支持转储:你可以给这个宝石一试在没有引入新的rake任务的情况下,开箱即用的触发器和函数。它基于tenderlove的trigger_happy插件。

0

看起来像(我还没有测试过)rake db:structure:dump支持已存储的函数和程序已被添加到Rails 5中。请参阅this commit in the rails GitHub project--routines标记到mysqldump被描述为here。注意方法structure_dump与JanMinárik在六年前回答时看起来非常不同。

0

On Rails的4我迷上它作为对db:test:load rake任务后吊钩如下:

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

,这样你就不必手动重新加载数据库每次测试运行这种方法会自动运行它只会影响db:test:load任务,所以我认为它是相当孤立的。

恕我直言,有一个丑陋的任务中有迁移标识,所以你可以选择将迁移代码提取到一个lib,并从上面的迁移和Rake任务中调用它来清理它。

相关问题