Существует ли обходной путь для переменных сеанса JDBC с liquibase и MySQL и инструкций SQL на стороне клиента? - PullRequest
2 голосов
/ 29 декабря 2010

Постепенно создайте начальный XML-файл changeSet для одной из трех основных схем моего работодателя. Единственный ограничитель показа включал в себя значительную библиотеку хранимых процедур MySQL, которые будут управляться liquibase.

С одним спроком пришлось столкнуться с болью: первые несколько утверждений выглядят как

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

Я исключил оператор использования из-за его непродуктивности, но настоящей проблемой является оператор set @@session.sql_mode, который вызывает исключение, подобное

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

И тогда оператор delimiter является еще одним камнем преткновения.

Проводя исследование трудолюбия, я обнаружил этот отклоненный отчет об ошибке MySQL здесь и эту ветку форума MySQL, которая немного углубляется в проблему здесь .

Могу ли я в любом случае использовать сценарии sproc, которые в настоящее время существуют в Liquibase, или мне придется переписать несколько сотен хранимых процедур?

Я попробовал теги createProcedure, sqlFile и sql liquibase без особой удачи, так как думаю, что основная проблема заключается в том, что set, delimiter и подобные команды SQL предназначены для интерпретации и обработки интерпретатором на стороне клиента перед доставкой на сервер.

Ответы [ 2 ]

4 голосов
/ 31 декабря 2010

Да, я думаю, что проблема в том, что ваш сценарий предполагает, что он будет работать через клиент mysql, который имеет дополнительные возможности, отсутствующие в JDBC.

Liquibase разделит ваши операторы по разделителю (по умолчанию; но может быть изменен с помощью атрибута разделителя), а затем направит каждый оператор в базу данных.Если вы указали $$ в качестве разделителя, вы можете удалить строку «delimiter $$», но перед каждой строкой должна быть строка;заменено на $$.Кроме того, есть другой специфичный для клиента SQL, такой как строка @@ session.Я думаю, что это может быть ненужным без прохождения через клиента, но я не совсем уверен, что он делает.

Вы должны быть в состоянии заставить ваши процедуры работать, но это займет некоторое переписывание.

Если вы не хотите переписывать все свои процедуры, вы можете использовать что-то вроде тега executeCommand , который позволит вам вызывать клиент mysql и вводить его в существующий скрипт.Вы теряете некоторые вещи, которые дает liquibase, например, режим updateSQL, и вы должны убедиться, что клиент mysql существует везде, где вы запускаете свой журнал изменений, но это избавит вас от необходимости переписывать свои сценарии.

2 голосов
/ 27 ноября 2012

Это сработало для меня: http://comments.gmane.org/gmane.comp.db.liquibase.user/480

Короче говоря, это говорит:

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