2010-12-29 10 views
2

Langsam Erstellen einer Starter-ChangeSet XML-Datei für eines von drei primären Schemas meines Arbeitgebers. Der einzige Show-Stopper ist die umfangreiche Bibliothek von gespeicherten MySQL-Prozeduren, die von liquibase verwaltet werden.Gibt es eine Problemumgehung für JDBC w/liquibase und MySQL-Sitzungsvariablen und clientseitige SQL-Anweisungen

Ein sproc hat etwas von einem Schmerz gewesen zu behandeln: Die ersten Aussagen wie

use TargetSchema; 
select "-- explanatory inline comment thats actually useful --" into vDummy; 

set @@session.sql_mode='TRADITIONAL' ; 

drop procedure if exists adm_delete_stats ; 

delimiter $$ 

create procedure adm_delete_stats(
...rest of sproc 

mir die Aussage Gebrauch gehen als kontraproduktiv herausgeschnitten, aber wirkliches Problem ist die set @@session.sql_mode Aussage, die bewirkt, eine Ausnahme wie

liquibase.exception.MigrationFailedException: Migration failed for change set ./foobarSchema/sprocs/adm_delete_stats.xml::1293560556-151::dward_autogen dward: 
Reason: liquibase.exception.DatabaseException: Error executing SQL ... 

Und dann die delimiter Aussage ist ein weiterer Stein des Anstoßes.

Bei der Doilligence-Untersuchung habe ich diesen abgelehnten MySQL-Fehlerbericht here und diesen MySQL-Forum-Thread gefunden, der ein wenig tiefer in das Problem eingeht here.

Kann ich die Sproc-Skripte, die derzeit mit Liquibase existieren, trotzdem verwenden oder müsste ich mehrere hundert gespeicherte Prozeduren neu schreiben?

Ich habe versucht, createProcedure, sqlFile und sql liquibase tags ohne viel Glück, wie ich denke, das Kernproblem ist, dass Satz, Trennzeichen und ähnliche SQL-Befehle interpretiert werden und von der clientseitigen Interpreter vor dem sein soll an den Server geliefert.

Antwort

4

Ja, ich denke, das Problem ist, dass Ihr Skript davon ausgeht, dass es über den mysql-Client läuft, der über zusätzliche Fähigkeiten verfügt, die in JDBC nicht vorhanden sind.

Liquibase teilt Ihre Anweisungen in das Trennzeichen auf (standardmäßig auf; kann aber mit dem Trennzeichenattribut geändert werden) und gibt dann jede Anweisung an die Datenbank weiter. Wenn Sie $$ als Trennzeichen angeben, können Sie die Zeile "delimiter $$" entfernen, aber jede Zeile davor muss den Wert; ersetzt durch $$. Außerdem gibt es noch andere mandantenspezifische SQL wie die @@ Session-Zeile. Ich denke, dass das unnötig sein kann, ohne den Kunden zu durchlaufen, aber ich bin mir nicht ganz sicher, was es tut.

Sie sollten in der Lage sein, Ihre Prozeduren zum Laufen zu bringen, aber es wird etwas Umschreiben erfordern.

Wenn Sie nicht alle Ihre Prozeduren neu schreiben möchten, könnten Sie etwas wie das executeCommand-Tag verwenden, mit dem Sie den mysql-Client aufrufen und Ihr vorhandenes Skript einspeisen könnten. Sie verlieren einige Dinge, die liquibase Ihnen wie den updateSQL-Modus bietet, und Sie müssen sicherstellen, dass der mysql-Client überall dort existiert, wo Sie Ihr changelog ausführen, aber es würde Sie davon abhalten, Ihre Skripte neu schreiben zu müssen.

+0

Gave erhalten Sie ein Votum für Mühe, ich kann/wird das Trennzeichen Aussage aber die @@ session.sql_mode Schrott Richtlinie ist eine nicht verhandelbare Anforderung. Für MySQL weist es die Client-Bibliothek an, alle Warnungen als Fehler zu behandeln, da MySQL keine echte Fehlerbehandlungslogik hat, manchmal können fatale Fehler in einem Sproc-Aufruf fast vollständig verloren oder heruntergestuft werden. Wenn der SQL-Modus bei der Erstellung einer Prozedur verschoben wird, wird die Prozedur in diesem Modus ausgeführt. – David

+0

Ansonsten ist vielleicht Ihr Vorschlag, executeCommand zu verwenden, machbar.Da ich Liquibase so eingerichtet habe, dass sie auf fast jeder Maschine in der Konstruktionsabteilung halbportabel ist, befinden sich die Datenbankberechtigungsnachweise in einer unabhängigen Skriptdatei, die sie temporär in das primäre Aufrufskript exportiert. Muss experimentieren, um zu sehen, ob executeCommand-Prozesse den Bereich ihrer Eltern erben. – David

2

Das ist für mich gearbeitet: http://comments.gmane.org/gmane.comp.db.liquibase.user/480

Kurz sagt es so:

<changeSet id="123321-4" author="ehrhardt"> 
    <sql>DROP PROCEDURE IF EXISTS curdemo;</sql> 
    <sql splitStatements="false" stripComments="false"> 
    <![CDATA[ 
     CREATE PROCEDURE curdemo() 
     BEGIN 
     DECLARE done INT DEFAULT 0; 
     blah.. 
     blah.. 
     END; 
    ]]> 
    </sql> 
    <sql>call curdemo();</sql> 
</changeSet> 
Verwandte Themen