16 Stimmen

Wie migriere ich gespeicherte Prozeduren in eine Test-DB?

Ich habe ein Problem mit gespeicherten Prozeduren und der Testdatenbank in Rails 3.0.7. Beim Ausführen

rake db:test:prepare

Es migriert die DB-Tabellen aus schema.rb und nicht direkt aus Migrationen. Die Prozeduren werden innerhalb der Migrationen durch Aufruf der execute-Methode und Übergabe eines SQL-Strings wie CREATE FUNCTION foo() ... BEGIN ... END; .

Nach Recherchen habe ich herausgefunden, dass man die

config.active_record.schema_format = :sql

innerhalb application.rb . Nachdem ich diese Zeile hinzugefügt hatte, führte ich Folgendes aus

rake db:struktur:dump rake db:test:clone_structure

Die erste soll die Struktur in eine development.sql Datei und die zweite erstellt die Testdatenbank aus dieser Datei. Aber meine gespeicherten Prozeduren und Funktionen werden immer noch nicht in der Testdatenbank angezeigt. Wenn jemand etwas über dieses Problem weiß. Hilfe wird geschätzt werden.

Ich habe auch versucht, rake db:test:prepare erneut auszuführen, aber immer noch keine Ergebnisse.

MySQL 5.5, Rails 3.0.7, Ruby 1.8.7.

Vielen Dank im Voraus!

9voto

Jan Minárik Punkte 3177

Es gibt keinen anderen Rake-Task dafür und structure_dump ist wie folgt definiert:

# 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

Es funktioniert also offensichtlich nur für Tabellen, nicht für Prozeduren, es sei denn, Sie monkeypachen es.

Die einzige Lösung, die ich kenne, ist die Verwendung von Shell:

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

1voto

RolandoMySQLDBA Punkte 42705

DISCLAIMER: Ich bin kein Ruby-on-Rails-Programmierer

Streng genommen gibt es in MySQL zwei Möglichkeiten, Stored Procedures (SP) und Stored Functions (SF) zu extrahieren.

Beachten Sie, dass mysql.proc und information_schema.routines das Gehäuse auf der Festplatte und im Speicher für SPs bereitstellen. Dennoch gibt es 2 SQL-Anweisungen, um sie abzurufen: ERSTELLUNGSVORGANG ANZEIGEN y FUNKTION "ERSTELLEN" ANZEIGEN .

Die erste Möglichkeit besteht darin, alle SPs und SFs mit mysql.proc zu sammeln und sie in SQL-Anweisungen umzuwandeln, die sie offenlegen.

Beispiel: Ich habe 6 SPs und 2 SFs in meiner Testdatenbank. Im Folgenden wird beschrieben, wie ich SQL für alle 8 Routinen generiere:

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)

Sie können die einzelnen gespeicherten Prozeduren und Funktionen durchgehen und den erforderlichen Code sammeln.

Auslöser müssen separat gesammelt werden.

In MySQL 5.x können Sie mit dieser Abfrage Auslöser sammeln:

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

oder um Zeit zu sparen, UNION die beiden SQL-Anweisungen

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)

Der zweite Weg ist der bevorzugte Weg für DBAs, die mysqldump verwenden.

Dadurch werden alle Tabellenstrukturen, SPs, SFs und Trigger in einer einzigen Datei gesammelt.

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

Dies macht dasselbe, aber ohne den CREATE TABLE-Kram:

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

Probieren Sie diese aus!!!

1voto

Russell Silva Punkte 2612

Sieht aus wie (ich habe nicht getestet) rake db:structure:dump Die Unterstützung für gespeicherte Funktionen und Prozeduren wurde in Rails 5 hinzugefügt. Siehe dieser Commit im Schienen-GitHub-Projekt . En --routines Flagge zu mysqldump wird beschrieben ici . Methode beachten structure_dump sieht ganz anders aus als vor sechs Jahren, als Jan Minárik antwortete.

0voto

Johann Tagle Punkte 106

Ich suchte nach einer Möglichkeit, dasselbe zu tun, und sah dies: http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps

Um zu zitieren:

"db/schema.rb kann keine datenbankspezifischen Elemente wie Fremdschlüssel-Constraints, Trigger oder Stored Procedures ausdrücken. Während Sie bei einer Migration benutzerdefinierte SQL-Anweisungen ausführen können, kann der Schema-Dumper diese Anweisungen nicht aus der Datenbank rekonstruieren. Wenn Sie solche Funktionen verwenden, sollten Sie das Schemaformat auf :sql setzen."

d.h.:

config.active_record.schema_format = :sql

Ich habe es allerdings noch nicht selbst ausprobiert, daher werde ich später einen Bericht darüber schreiben.

0voto

Jae Cho Punkte 459

Ich habe die Methode von Matthew Bass zum Entfernen eines vorhandenen Rake-Tasks übernommen und einen Task mit mysqldump und den von RolandoMySQLDBA angegebenen Optionen neu definiert

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X