Adding a / as an end delimeter on Liquibase Oracle SQL statement - liquibase

While using Liquibase feature, I extended liquibase.sqlgenerator.core.CreateIndexGenerator class to convert this command
create index indexI on tableT(columnC)
into something like this:
declare
index_already_exists exception;
pragma exception_init(index_already_exists, -955);
--
begin
execute immediate 'create index indexI on tableT(columnC)';
exception
when index_already_exists then
dbms_output.put_line('Warning: Index indexI already exists');
end;
to make it idempotent and create some new validations.
It is working perfectly when using mvn liquibase:update. But, when generating the SQL using mvn liquibase:updateSQL a final / (slash) is missing.
Looking at Liquibase sourcecode I found out that the class LoggingExecutor used to have what I need on method outputStatement
} else if (database instanceof OracleDatabase) {
output.write(StreamUtil.getLineSeparator());
output.write("/");
I tried to add a final / (slash) after the end; if, but it becomes like this :
end;
/;
which is invalid PLSQL code
Is there another way to add a final / on the SQL generated code, or set the / as an end delimeter ?

Instead of extending CreateIndexGenerator you could instead override CreateIndexChange.generateStatements() to return a RawSqlStatement with your SQL. That allows you to better set the end delimiter and may work better with the LoggingExecutor.

I'm using liquibase 3.4.2 and the end delimiter / is recognized automatically. When I mean automatically you don't have to use the property endDelimiter in the declaration of the changeset. It turns out that in some older versions of liquibase a bug was introduced during the parsing.
Please check http://www.liquibase.org/2015/06/liquibase-3-4-0-released.html
and you will see that they fix the issue https://liquibase.jira.com/browse/CORE-2227. This issue was affecting the version 3.3.2.
So I suggest you to use a newer version or specify correctly the endDelimiter property in the declaration of the changeset.
http://www.liquibase.org/documentation/changes/sql.html

Related

Inno Setup: Iterate/Enumerate through Firewall Rules / IEnumVariant

I have a similar question like Daniel Rogers about how to declare an IEnumVariant in Inno Setup.
Declare an OleVariant and IEnumVariant in Inno Setup
I'm writing some extra functionality for our setup, in this case I want to add and remove firewall rules during install/uninstall. There are plenty good pointers with examples on the internet to do that. So that's not the problem, it's already done.
But now I want to iterate/enumerate the existing firewall rules but that's the part where I'm struggling with :-( I can't get it to work, unfortunately Inno Setup doesn't recognize the IEnumVariant type so the examples who's are
written in Delphi are not going to work.
If I lookup the Microsoft API documentation about the INetFwRules interface
https://learn.microsoft.com/en-us/windows/win32/api/netfw/nn-netfw-inetfwrules then it looks like it that the only
way to enumerate/iterate is to use the _NewEnum function. (which is returning an IEnumVariant)
So does anybody have some pointers (or mini example) to work around or deal with the above problem?
I also have some issue's when I'm trying to get one single rule through the FwRules.Item function, Inno Setup just keeps saying
"Ongeldig aantal parameters" (something like "invalid parameter count").
var
lcFwPolicy : Variant;
lcFwRules : Variant;
lcFwRule : Variant;
//lcEnum : IVariantEnum;
begin
try
lcFwPolicy := CreateOleObject('HNetCfg.FwPolicy2');
lcFwRules := lcFwPolicy.Rules;
lcFwRules.Item('a fwrule name', lcFwRule); <----- this call is causing "invalid parameter count"
except
Log(GetExceptionMessage);
Log('>>> FirewallRuleExists Exception !!!');
end;
end;
But the most important part of my question is about the enumeration of the firewall rules, if that is possible then the other question is less important.
I'll hope there is somebody out there with the golden solution/workaround.

Dynamic Procedure BigQuery

Does Bigquery support dynamic procedure calls? I am looking to generate a procedure name as string based on variables and call the string.
EXECUTE IMMEDIATE returns this error clearly it doesn't support CALL. Is there any other way?
SQL created by EXECUTE IMMEDIATE contains unsupported statement type: CallStatement.
Thank you.
I make this answer for visibility, the approach you can use is as follow (as mention in the comments by mikhail):
CREATE OR REPLACE PROCEDURE `project-id.dataset`.maker(option INT64)
BEGIN
IF option=1 THEN
CALL `project-id.dataset`.create_user(); #call to procedure
ELSEIF option=2 THEN
CALL `project-id.dataset`.create_customer(); #call to procedure
ELSE
SELECT "END"; #default
END IF;
END
to use
CALL `project-id.dataset`.maker(2)
As stated in the comments, execute immediate do not support at the moment the usage of call.
I also found a feature request about supporting using call with execute immediate on google issue tracker you can leave a comment to support the feature request.

Trigger Procedure Not Showing Up In Staging/Production

So I have this trigger procedure in my structure.sql:
CREATE FUNCTION dead_filter() RETURNS TRIGGER AS $dead_filter$
BEGIN
IF (NEW.all_votes > 6 AND NEW.non_skip_votes/NEW.all_votes::float < 0.56) THEN
NEW.dead := true;
RETURN NEW;
END IF;
RETURN NEW;
END;
$dead_filter$ LANGUAGE plpgsql;
CREATE TRIGGER dead_filter AFTER UPDATE ON statements
FOR EACH ROW
EXECUTE PROCEDURE dead_filter();
And it works locally just fine, but for some reason it is showing up in my staging and production servers!
Both live on a heroku app, and both have
config.active_record.schema_format = :sql
in their relevant config files. What am I missing here?
select * from pg_trigger;
doesn't include my trigger on staging/production, but DOES locally, on development.
Is there something I need to run to have the structure.sql file re-read? Backend is definitely my weak spot, so if there's something super obvious I should've known to do...odds are I didn't know to do it!
Thanks!
As in a comment, you need to create a migration that adds a trigger and run this migration on production as it is not automatic on Heroku. Also please note that structure.sql file will be regenerated after running migrations locally or task such as rake db:schema:dump. So you shouldn't edit this file manually.

Groovy Sql Execute Statement won't accept closures

I have a statement:
sqlInstance.execute(executeString){
dummy, realList->
debug("Real LIst: "+realList)
}
which fails with 'Invalid column type'
But:
def bool = sqlInstance.execute(executeString)
works. If I print bool, it prints as 'true'.
For reference:
executeString = "select distinct channel_id from guide_sched"
For some reason, the closure isn't working for the execute method in groovy's Sql, although I've checked the documentation and it's supposed to.
It looks like the first environment I was testing on ran Groovy 2.4 and the second runs Groovy 2.1. The execute statement I was using didn't exist until after 2.1
Instead, I used the .rows() function to return a GroovyRowResult which I parsed for the information I needed, instead of accessing it directly in the .execute() closure.

Executing the contents of a memo on a TADOQuery

I have a really long list of sql commands on a memo, when I try to execute it I get the following error:
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
The code to execute it:
Query.SQL.Text := Memo1.Lines.Text;
Query.ExecSQL;
I have a vague idea that the error is caused due to the way the query content was added, so, here's how I'm doing it now:
1) Memo1.Lines.LoadFromFile('Patch.sql');
2) Proceed to the query commands
As you can see, the contents of the memo is loaded from a file. Is there any other way to successfully do this?
P.S.: I'm using Microsoft SQL 2008.
Thank you!
It looks like you're not using parameters, so set ParamCheck off
Query.ParamCheck := false;
If there is a colon ":" in a string in the SQL, the TADOQuery thinks it's a parameter