Как перенести хранимые процедуры на тестирование db?
У меня проблема с хранимыми процедурами и тестовой базой данных в Rails 3.0.7. При запуске
rake db: test: подготовить
он переносит таблицы db из schema.rb, а не непосредственно из миграций. Процедуры создаются в рамках миграций, вызывая метод execute и передавая строку SQL, такую как CREATE FUNCTION foo() ... BEGIN ... END;
.
Итак, после исследования я обнаружил, что вы должны использовать
config.active_record.schema_format =: sql
внутри application.rb
. После добавления этой строки я выполнил
rake db: structure: dump rake db: test: clone_structure
Первый должен сбрасывать структуру в файл development.sql
, а второй создает тестовую базу данных из этого файла. Но мои хранимые процедуры и функции все еще не отображаются в тестовом db. Если кто-то знает что-то об этой проблеме.
Помощь будет оценена.
Я также попробовал запустить rake db: test: снова подготовить, но все равно никаких результатов.
MySQL 5.5, Rails 3.0.7, Ruby 1.8.7.
Спасибо заранее!
Ответы
Ответ 1
Для этого нет другой задачи rake, а struct_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
поэтому он, по-видимому, работает только для таблиц, а не для процедур, если вы не обезьете его.
Единственное решение, которое я знаю, это использовать оболочку:
mysqldump -R -u <user> <development_database> | mysql -u <user> <test_database>
Ответ 2
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я не программист Ruby-on-Rails
Строго с точки зрения MySQL у вас есть два способа извлечь хранимые процедуры (SP) и хранимые функции (SF).
Имейте в виду, что mysql.proc и information_schema.routines предоставляют корпус на диске и в памяти для SP. Тем не менее, для их получения есть 2 оператора SQL: ПОКАЗАТЬ ПРОЦЕДУРА СОЗДАНИЯ и ПОКАЗАТЬ CREATE FUNCTION.
Первый способ включает сбор всех SP и SF с помощью mysql.proc и формирование их в операторы SQL, которые их раскрывают.
Пример. В моей тестовой базе данных есть 6 SP и 2 SF. Вот как создать SQL для всех 8 подпрограмм:
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
Дайте им попробовать!!!
Ответ 3
Искал, как сделать то же самое, а потом увидел это: http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps
Цитата:
"db/schema.rb не может выражать конкретные элементы базы данных, такие как ограничения внешнего ключа, триггеры или хранимые процедуры. В процессе миграции вы можете выполнять пользовательские инструкции SQL, а самозагружатель схемы не может восстановить эти утверждения из базы данных. используя такие функции, вы должны установить формат схемы: sql."
то есть:.
config.active_record.schema_format =: sql
Я еще не пробовал себя, но я отправлю последующее сообщение позже.
Ответ 4
Я взял метод Matthew Bass для удаления существующей задачи рейка и переопределил задачу с помощью 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
Ответ 5
Если вам нужны дампы Ruby (в отличие от дампов SQL), вы можете попробовать этот камень:
https://github.com/jovoto-team/trackless_triggers
Он поддерживает триггеры загрузки и функции для mysql из коробки, не вводя новые задачи rake. Он основан на плавнике trigger_happy.
Ответ 6
Похоже, что я не тестировал. rake db:structure:dump
поддержка сохраненных функций и процедур была добавлена в Rails 5. См. это фиксация в рельсах GitHub проект. Флаг --routines
на mysqldump
описывается здесь. Метод примечаний structure_dump
выглядит очень иначе, чем когда Ян Минарик ответил шесть лет назад.
Ответ 7
В Rails 4 я зацепил его как крюк после нагрузки в db:test:load
rake task следующим образом:
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 каждого тестового прогона, и он будет влиять только на задачу db:test:load
, поэтому я считаю, что он достаточно изолирован.
IMHO немного уродливый с идентификаторами миграции в задаче, поэтому вы также можете извлечь код миграции в lib и вызвать его как из миграции, так и из задачи Rake выше, чтобы очистить ее.