Как перенести хранимые процедуры на тестирование 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 выше, чтобы очистить ее.