I am trying to generate SQL Output script, which I will run from Ant (via …) or in SQL Developer (a client application from Oracle). However, both these methods require some blocks (e.g. create or replace type…, create or replace trigger …) to be followed by a single line containing only a forward-slash. I cannot find a way to do this in LiquiBase, am I missing something?
This sounds like a feature that was inexplicably removed for v1.9.
It does look like it was removed in favor of the ; line terminators. The default line terminator string is returned by the OracleDatabase class. If you use the databaseClassName attribute, you can specify your own subclass of OracleDatabase that overrides the defaultSeparator method.
I believe there is an attribute on to specify the end delimiter, but I don’t think it will allow you to say “\n/”. I created a feature request to allow something like that (http://liquibase.jira.com/browse/CORE-406).
In our environment, we definitely need to be able to generate scripts that can be reviewed by our DBA. I think that is a common scenario. However, generating scripts that will run successfully and reliably in all three cases listed above (Ant Task, SQL*Plus, SQLDeveloper) is tricky. In fact, I’ve not been able to successfully achieve even one of those.
The root of the problem is the handling of triggers, procedures, and other “blocks” vs. handling of “statements”. I think I understand correctly that blocks require a delimiter (by default, “/” on a line by itself) after the end of the block.
I will build my own subclass to accomplish what’s needed (if I can identify a comprehensive solution), but I’m really surprised that no one has already addressed this. Perhaps I overestimate the intersection of Liquibase users and Oracle users.
Maybe there is confusion about the block separator versus the PL/SQL command separator. In SQL*Plus these can sometimes be interchanged. In PL/SQL, only a semicolon can be used, and a semi-colon must trail the last END statement. This is part of the PL/SQL block. You then require a / to execute the block.
I am having success executing trigger and procedure blocks via an updateDatabase task, but I’m still not sure what to do to generate the proper scripts. I’ll look closer at the link you included.
applying changes directly via liquibase is used only for dev purposes
for production purposes we generate script which is passed to dba
Adding a slash to the end of each statement was a bad choice because sqlplus treats slash as a buffer flush. For procedure/triggers/functions it is a must: because content of if is stored in the buffer and is not executed. However, for all other statements it means executing the same statement twice because such statement is executed immediately and put into buffer and following slash just re-executes the same statement.
We have found following workaround to the problem:
a) because changeset accepts multiple tags so we create first for procedure and right after it a dummy like this:
select 1 from dual
b) then in ant build.xml we generate script and right after it we postprocess it with replace task: we replace above dummy sql with a slash. Since dummy sql is harmless so in applying mode it does not matter.
I think instead of extending xml schema to accept things like end separator etc. I would focus on API which would allow control of generated script. Such API would accept a callback interface which would be called in certain places of generated script (f.e. right after the statement is outputed). Callback method could get a type of statement (raw sql OR create procedure). In case it is a create procedure tag then callback could add following slash to tackle sqlplus issue. Callback could be created manually by the user OR there would be out of the box callbacks for particular use cases: f.e. sqlplus. To have even more flexibility sql tags (and others) could accept an attribute called f.e. label which would be any name given by the user which would be passed to the callback: thus, callback could have more meta info about the statement.
So generally it would be good to have an API for generating script which would allow plugging in a post processor mechanism: to allow customization driven by users and/or execution tools (sqlplus etc.).