I can't get my function to work in the liquibase changeset.
This function is good working on the IntelliJ IDEA:
CREATE OR REPLACE FUNCTION get_value() RETURNS varchar AS
$$
SELECT varchar '170d76f83d90ea1427' AS result;
$$ LANGUAGE SQL;
But it fails when trying to run it in the liquibase changeset like this:
<changeSet author="akulik" id="test-014-002">
<sql>
CREATE OR REPLACE FUNCTION get_value() RETURNS varchar AS
$$
SELECT varchar '170d76f83d90ea1427' AS result;
$$ LANGUAGE SQL;
</sql>
<rollback>
<sql>
DROP FUNCTION get_secret();
</sql>
</rollback>
</changeSet>
I'm catching this exception:
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.2.2:update (default-cli) on project my_liquibase_project: Error setting up or running Liquibase: Migration failed for change set db/com/akulik/test/db/changesets/db.changelog-014.xml::test-014-002::akulik:
[ERROR] Reason: liquibase.exception.DatabaseException: Error executing SQL CREATE OR REPLACE FUNCTION get_secret() RETURNS varchar AS
[ERROR] $$
[ERROR] SELECT varchar '170d76f83d90ea1427' AS result: ERROR: unterminated dollar-quoted string at or near "$$
[ERROR] SELECT varchar '170d76f83d90ea1427' AS result"
[ERROR] Position: 68
[ERROR] ->
I think that I should correctly shield my function. I tried this way but it didn't work and I received the same error message.
I continue to find a solution in this way.
<changeSet author="akulik" id="test-014-002">
<sql><![CDATA[
CREATE OR REPLACE FUNCTION get_value() RETURNS varchar AS
$$
SELECT varchar '170d76f83d90ea1427' AS result;
$$ LANGUAGE SQL;
]]></sql>
<rollback>
<sql>
DROP FUNCTION get_secret();
</sql>
</rollback>
</changeSet>
I found out about <createProcedure> tag and used it instead of <sql> tag in my changeset definition. That's resolved my problem. Now it's working fine.
Related
So, i need to make a function that can generate schema & table that schema name and table name depend on parameter send called _schema_name for schema name & _tp_table_name for table name.
My pgsql function code right now :
CREATE OR REPLACE FUNCTION public.addschema(_schema_name character varying, _tp_table_name character varying )
RETURNS character varying
LANGUAGE plpgsql
AS $function$
begin
execute format('CREATE schema %I',_schema_name);
execute format('CREATE TABLE %I.%I( id uuid NOT NULL DEFAULT uuid_generate_v4(),
raw_id uuid NULL)', _schema_name, _tp_table_name);
RETURN _schema_name;
END;
$function$
;
so i run the function with this :
select addschema('newschema','new_tbl');
i've got an error like this :
SQL Error [22023]: ERROR: unrecognized format() type specifier "I"
Hint: For a single "%" use "%%".
Where: PL/pgSQL function addschema(character varying,character varying) line 11 at EXECUTE
anyone have any hints? thank you..
The problem has to be somewhere in the client side. Your function looks just fine. I've tested it (slightly formatted) in psql, pgAdmin4 and DBeaver 21.2.0.202108310918.. all worked just fine:
CREATE OR REPLACE FUNCTION public.addschema(_schema_name text, _tp_table_name text )
RETURNS text
AS $$
BEGIN
EXECUTE format('CREATE SCHEMA %I;',_schema_name);
EXECUTE format('CREATE TABLE %I.%I( id uuid NOT NULL DEFAULT uuid_generate_v4(),
raw_id uuid NULL)', _schema_name, _tp_table_name);
RETURN _schema_name;
END
$$ LANGUAGE plpgsql;
DBeaver screenshot:
Alternatively, you can take look at the database log files to see how the query is actually being sent to the database. Also, in case you're using an older PostgreSQL version, format() is supported only after PostgreSQL 9.6+
I get the above error coming from Play Evolutions while running activator run on a new Scala Play-Slick project. I'm using Postgres server version 9.3 and the latest JDBC driver 9.4. My 1.sql file looks like this:
# schema
# --- !Ups
CREATE TABLE country (
id BIGINT,
name VARCHAR(100),
iso2 CHAR(2),
modified TIMESTAMP DEFAULT now(),
PRIMARY KEY (id)
);
CREATE OR REPLACE FUNCTION update_modified()
RETURNS TRIGGER AS $$
BEGIN
NEW.modified = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER trigger_country_modified BEFORE UPDATE ON country FOR EACH ROW EXECUTE PROCEDURE update_modified();
# --- !Downs
DROP TABLE country CASCADE;
DROP FUNCTION update_modified_column;
By trial and error I see that Evolutions doesn't understand well the native Postgres trigger function update_modified. How can I solve or circumvent this issue?
The Play evolution plugin splits your .sql files into a series of semicolon-delimited statements before executing them one-by-one against the database.
As you are using semicolons within the function update_modified() code, you have to escape it by entering it twice ;;. See below:
CREATE OR REPLACE FUNCTION update_modified()
RETURNS TRIGGER AS $$
BEGIN
NEW.modified = now();;
RETURN NEW;;
END;;
$$ language 'plpgsql';
In order to use retry.attempts in liquibase :
<sql>ALTER TABLE t set t.name = 'CI_CASE' where t.retry_attempts >= 1000</sql>
not sure how can i ADD a Column to table CI_CASE
so i tried a simpler statement:
<sql>ALTER TABLE CI_CASE ADD COLUMN TNUM</sql>
but i get Exception:
liquibase.exception.DatabaseException: Error executing SQL ALTER TABLE CI_CASE ADD COLUMN TNUM: ORA-00904: : invalid identifier
I have tried appending ";" semicolon, and trying:
<sql>ALTER TABLE t set t.name = 'CI_CASE' and t.column = 'TNUM' where t.retry_attempts >= 1000</sql>
which is my ultimate Goal , is to use retry.attempts for liquibase
so the error was due to Syntax, and the following SQL statement in the .sql file passed:
ALTER TABLE CI_CASE ADD TNUM varchar2(1) NOT NULL;
Now need to figure out how to use :
put ‘max.retry.count’ in to liquibase.property file.
e.g parameter.max.retry.count=30
perhaps as an argument, to the :
<sqlFile path="oracle/schemas/ci_case.sql"/>
i tried:
ALTER TABLE CIS_CASE ADD TNUM varchar2(1) NOT NULL WHERE CIS_CASE.retry_attempts >= ${max.retry.count};
Liquibase update Failed: Migration failed for change set edata-changelog.xml::2016-08-25-cnwill::CW:
00:03:34.886 Reason: liquibase.exception.DatabaseException: Error executing SQL ALTER TABLE CIS_CASE ADD TNUM varchar2(1) NOT NULL WHERE CIS_CASE.retry_attempts >= $ax.retry.count}: ORA-01735: invalid ALTER TABLE option
notice the { and m , missing in the error log, not sure why is that so ?
i tried:
for Database/oracle/schemas/eldata/eldata-changelog.xml
<changeSet id="2016-08-25-cna-01" author="Ch Wills">
<comment>
Testing retry logic on liquibase
</comment>
<sqlFile path="oracle/schemas/eldata/2016-08/2016-08-25-cna-01/20160825_01_upd-data-elis2data-cis_case_kr.sql"/>
</changeSet>
This works, but now we want to incorporate a variable max.retry.count
So I use the property file:
liquibase.property
With:
parameter.max.retry.count=30
And call this in the changeset as:
<changeSet id="2016-08-25-cna-01" author="Ch Wills">
<comment>
Testing retry logic on liquibase
</comment>
<sqlFile path="oracle/schemas/eldata/2016-08/2016-08-25-cna-01/20160825_01_upd-data-eldata-cis_case_kr.sql”/>
<property name="max.retry.count" value="100" />
</changeSet>
Error:
[ERROR] [system.err] Liquibase update Failed: Error parsing line 10730 column 50 of /opt/jenkins/workspace/EL-FT-DBV-LIQUIBASE-RETRY/Apps/Database/oracle/schemas/eldata/eldata-changelog.xml: cvc-complex-type.2.4.a: Invalid content was found starting with element 'property'. One of
'{"http://www.liquibase.org/xml/ns/dbchangelog":comment, "http://www.liquibase.org/xml/ns/dbchangelog":createTable, "http://www.liquibase.org/xml/ns/dbchangelog":dropTable, "http://www.liquibase.org/xml/ns/dbchangelog":createView, "http://www.liquibase.org/xml/ns/dbchangelog":renameView, "http://www.liquibase.org/xml/ns/dbchangelog":dropView, "http://www.liquibase.org/xml/ns/dbchangelog":insert, "http://www.liquibase.org/xml/ns/dbchangelog":addColumn, "http://www.liquibase.org/xml/ns/dbchangelog":sql, "http://www.liquibase.org/xml/ns/dbchangelog":createProcedure, "http://www.liquibase.org/xml/ns/dbchangelog":sqlFile, "http://www.liquibase.org/xml/ns/dbchangelog":renameTable, "http://www.liquibase.org/xml/ns/dbchangelog":renameColumn, "http://www.liquibase.org/xml/ns/dbchangelog":dropColumn, "http://www.liquibase.org/xml/ns/dbchangelog":mergeColumns, "http://www.liquibase.org/xml/ns/dbchangelog":modifyDataType, "http://www.liquibase.org/xml/ns/dbchangelog":createSequence, "http://www.liquibase.org/xml/ns/dbchangelog":alterSequence, "http://www.liquibase.org/xml/ns/dbchangelog":dropSequence, "http://www.liquibase.org/xml/ns/dbchangelog":createIndex, "http://www.liquibase.org/xml/ns/dbchangelog":dropIndex, "http://www.liquibase.org/xml/ns/dbchangelog":addNotNullConstraint, "http://www.liquibase.org/xml/ns/dbchangelog":dropNotNullConstraint, "http://www.liquibase.org/xml/ns/dbchangelog":addForeignKeyConstraint, "http://www.liquibase.org/xml/ns/dbchangelog":dropForeignKeyConstraint, "http://www.liquibase.org/xml/ns/dbchangelog":dropAllForeignKeyConstraints, "http://www.liquibase.org/xml/ns/dbchangelog":addPrimaryKey, "http://www.liquibase.org/xml/ns/dbchangelog":dropPrimaryKey, "http://www.liquibase.org/xml/ns/dbchangelog":addLookupTable, "http://www.liquibase.org/xml/ns/dbchangelog":addAutoIncrement, "http://www.liquibase.org/xml/ns/dbchangelog":addDefaultValue, "http://www.liquibase.org/xml/ns/dbchangelog":dropDefaultValue, "http://www.liquibase.org/xml/ns/dbchangelog":addUniqueConstraint, "http://www.liquibase.org/xml/ns/dbchangelog":dropUniqueConstraint, "http://www.liquibase.org/xml/ns/dbchangelog":customChange, "http://www.liquibase.org/xml/ns/dbchangelog":update, "http://www.liquibase.org/xml/ns/dbchangelog":delete, "http://www.liquibase.org/xml/ns/dbchangelog":loadData, "http://www.liquibase.org/xml/ns/dbchangelog":loadUpdateData, "http://www.liquibase.org/xml/ns/dbchangelog":executeCommand, "http://www.liquibase.org/xml/ns/dbchangelog":stop, "http://www.liquibase.org/xml/ns/dbchangelog":rollback, WC[##other:"http://www.liquibase.org/xml/ns/dbchangelog"], "http://www.liquibase.org/xml/ns/dbchangelog":modifySql}' is expected.
So that seems to be the list of property name’s I can use
Therefore it seems liqubibase does not have any “RETRY” property.
seems SQL itself provides looping based on the error code being received:
BEGIN
FOR i IN 1..5 LOOP -- Try transaction at most 5 times.
DBMS_OUTPUT.PUT('Try #' || i);
BEGIN -- sub-block begins
SAVEPOINT start_transaction;
-- transaction begins
DELETE FROM results WHERE res_answer = 'NO';
INSERT INTO results (res_name, res_answer) VALUES (name, answer);
-- Nonunique name raises DUP_VAL_ON_INDEX.
-- If transaction succeeded:
COMMIT;
DBMS_OUTPUT.PUT_LINE(' succeeded.');
EXIT;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE(' failed; trying again.');
ROLLBACK TO start_transaction; -- Undo changes.
suffix := suffix + 1; -- Try to fix problem.
name := name || TO_CHAR(suffix);
END; -- sub-block ends
END LOOP;
END;
Is that the only way, i can provide retry in liquibase for SQL ? if so, then, is there a way i can use a variable in place of 5 , in the 1..5 loop ?
I am converting a few simple MySQL stored procedures to PostgreSQL Functions and for some reason when I execute the following function it throws an error when executed.
I created the function with the following code:
CREATE FUNCTION cc.fs_ivr_updatecalltransfer(_ParentContactID
int[11], _CalledID varchar[32])
RETURNS int AS $$
DECLARE
pcID int;
BEGIN
if _ParentContactID<>0 then
update cc.tblcontacts set cc.tblcontacts.transferdest =
_CalledID where cc.tblcontacts.contactid =
_ParentContactID;
end if;
RETURN _ParentContactID;
END;
$$ LANGUAGE plpgsql;
I Execute it manually like this:
SELECT cc.fs_ivr_updatecalltransfer(3,"test")
It throws this error:
SQL error:
ERROR: column "test" does not exist
LINE 1: SELECT cc.fs_ivr_updatecalltransfer(3,"test")
In statement: SELECT cc.fs_ivr_updatecalltransfer(3,"test")
Any Suggestions?
Use single quotes to quote strings, not double quotes. 'test' means the string "test", whereas "test" means the identifier "test", which postgresql tries to resolve as a column, same as using backquotes in MySQL.
I have a table for which i have written a trigger:
CREATE OR REPLACE TRIGGER ac01_control_trigg
AFTER INSERT ON ac1_control_test
FOR EACH ROW
DECLARE
BEGIN
IF :NEW.cur_pgm_name = 'LSN'
AND :NEW.nxt_pgm_name ='MD'
AND :NEW.file_status='RD' THEN
INSERT INTO ac1_control_test
(FILE_NAME, FILE_PATH,FILE_STATUS,CUR_PGM_NAME,NXT_PGM_NAME)
VALUES
(:NEW.FILE_NAME, :NEW.FILE_PATH,:NEW.FILE_STATUS,:NEW.CUR_PGM_NAME,'MD_MPS');
END IF;
END ac01_control_trigg;
when i am trying to insert into the table i am getting an error below!
ORA-04098: trigger 'CNGDB18.AC01_CONTROL_TRIGG' is invalid and failed re-validation
could anybody please help?
also when i compile the trigger in Toad,i am getting compile errors as below:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/65 PLS-00049: bad bind variable 'NEW_FILE_STATUS'
but what is the wrong with this?
and what does this error mean?
EDIT: Now that we see the message, the solution is easy :)
Use :NEW.file_status='RD' instead of:new_file_status='RD'
Your trigger object is invalid (there is a problem with the code).
Test this with:
SELECT object_name, status
FROM user_objects
WHERE object_name = 'AC1_CONTROL_TRIGG';
Should return:AC1_CONTROL_TRIGG INVALID
You can try the following in SQL*Plus to get a description of the error:
ALTER TRIGGER ac1_control_trigg COMPILE;
SHOW ERROR TRIGGER ac1_control_trigg;
Using TOAD, you can just type these two lines into an editor, select them and use Editor>Execute SQL via SQL*Plus.