ArrayIndexOutOfBoundsException when running Liquibase - sql

I am using Spring and Liquibase to deploy the following SQL code:
BEGIN;
CREATE OR REPLACE FUNCTION public.get_clear_name_city(IN dirty TEXT, OUT clear TEXT) AS $$ SELECT trim(regexp_replace(regexp_replace(trim(dirty), '^(г |пгт |рп |кп |п |к |нп |п.ст |п ж/д ст |г. |пгт. |рп. |кп. |дп. |гп. |п. |к. |нп. |п.ст. |п. ж/д ст|п. ж/д ст.|п ж/д ст. |ж/д блокпост |ж/д будка |ж/д ветка |ж/д казарма |ж/д комбинат |ж/д платформа |ж/д площадка |ж/д путевой пост |ж/д остановочный пункт |ж/д рзд |ж/д ст |местечко |д |с |сл |ст |ст-ца |у |х |рзд |д. |с. |м |м. |сл. |ст. |у. |х. |рзд. |зимовье |город |гидрологический пост |поселок городского типа |рабочий поселок |рабочий посёлок |курортный поселок |дачный поселок |городской поселок |поселок |посёлок |кишлак |населенный пункт |поселок при станции (поселок станции) |поселок при железнодорожной станции |железнодорожный блокпост |железнодорожная будка |железнодорожная ветка |железнодорожная казарма |железнодорожный комбинат |железнодорожная платформа |железнодорожная площадка |железнодорожный путевой пост |железнодорожный остановочный пункт |железнодорожный разъезд |железнодорожная станция |местечко |межселенные территории |метеостанция |монтерский пункт |деревня |село |сельское поселение |городское поселение |слобода |станция |станица |улус |усадьба |хутор |разъезд |зимовье )?', '', 'i'), '( сельское поселение| городское поселение)$', '', 'i')); $$ LANGUAGE SQL;
CREATE OR REPLACE FUNCTION public.get_clear_name_state(IN dirty TEXT, OUT clear TEXT) AS $$ SELECT trim(regexp_replace(regexp_replace(regexp_replace(trim(dirty), '^(город |городской округ |г |г. |закрытое административно-территориальное образование город |муниципальное образование город |муниципальное образование |муниципальный район |муниципальный р-н |м.район |мун.район |м. район |мун. район |р |р. |р/н |р-н )?', '', 'i'), ' республики.*', '', 'i'), '( район| р| р.| р/н| р-н| сельское поселение| городское поселение| муниципальный район| м.район| мун.район| м. район| мун. район| город| городской округ| г| г.| закрытое административно-территориальное образование| муниципальное образование)$', '', 'i')); $$ LANGUAGE SQL;
DELETE FROM city;
DELETE FROM state;
CREATE TYPE oktmo_name AS (oktmo TEXT, name TEXT);
CREATE OR REPLACE FUNCTION city_set(parent_oktmo INTEGER)
RETURNS SETOF oktmo_name AS $$
BEGIN
RETURN QUERY EXECUTE
'WITH RECURSIVE cities_oktmo AS (
SELECT * FROM oktmo WHERE oktmo.parent_id = ' || parent_oktmo ||
'UNION ALL
SELECT oktmo.* FROM oktmo
JOIN cities_oktmo ON oktmo.parent_id = cities_oktmo.id
)
SELECT city.oktmo::TEXT, city.name::TEXT FROM cities_oktmo city
LEFT JOIN cities_oktmo child ON city.id = child.parent_id
WHERE child.oktmo ISNULL AND char_length(city.oktmo) = 11
ORDER BY city.name';
END; $$ LANGUAGE plpgsql;
DO $$
DECLARE
state_cursor CURSOR FOR
SELECT oktmo, name FROM oktmo
WHERE parent_id = (select m.value::BIGINT from "public"."messages" m WHERE m.key='branding.region.oktmo'); state_guid UUID;
BEGIN
FOR st IN state_cursor LOOP
state_guid := uuid_generate_v4();
INSERT INTO state(guid, oktmo, name, clear_name) VALUES(state_guid, st.oktmo, st.name, get_clear_name_state(st.name));
INSERT INTO city(oktmo, name, clear_name, state_guid)
SELECT oktmo, name, get_clear_name_city(name), state_guid
FROM city_set(st.oktmo::INT4);
END LOOP;
END $$;
DROP FUNCTION city_set(parent_oktmo INTEGER);
DROP TYPE oktmo_name;
COMMIT;
When I try to start up my application I get the following exception:
Caused by: liquibase.exception.MigrationFailedException: Migration failed for change set classpath:changelogs/db-changelog-4.x.xml::GEO-6154_1::kadzhaev:
Reason: java.lang.ArrayIndexOutOfBoundsException
I think it could happen because of $$ sign but how I can fix it?

Just add splitStatements="false" and stripComments="false" to the <sql> label.
<changeSet id="1" author="admin">
<sql splitStatements="false" stripComments="false" >
<![CDATA[
your SQL
]]>
</sql>
</changeSet>

I have the same issue and I have resolved using
<createProcedure dbms="postgresql"
encoding="utf8"
path="yourFunction.sql"
relativeToChangelogFile="true"
/>

Related

SnowSQL, procedure - error 904 when using variable in insert statement

I'm working on snowflake procedure in snowsql and want to use variable as value in insert statement - something like that:
execute immediate $$
declare
select_statement string;
begin
select_statement := '''Some text''';
INSERT INTO SOME_TABLE(MESSAGE) values (select_statement);
exception
when statement_error then
return object_construct('Error type', 'STATEMENT_ERROR',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
when other then
return object_construct('Error type', 'Other error',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
end;
$$
;
{
"Error type": "STATEMENT_ERROR",
"SQLCODE": 904,
"SQLERRM": "SQL compilation error: error line 1 at position 102\ninvalid identifier 'SELECT_STATEMENT'",
"SQLSTATE": "42000"
}
I was trying to use single quote as well
select_statement := 'Some text';
and also without declaring it and using let
let select_statement := 'Some text';
Each time getting the same error...
please try this.
create or replace table SOME_TABLE(MESSAGE varchar2 );
select * from SOME_TABLE;
execute immediate $$
declare
select_statement string;
begin
select_statement := '''Some text''';
INSERT INTO SOME_TABLE(MESSAGE) values (:select_statement);
exception
when statement_error then
return object_construct('Error type', 'STATEMENT_ERROR',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
when other then
return object_construct('Error type', 'Other error',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
end;
$$;
This just needs some minor adjustments to the syntax. To use execute immediate as a string, create the string with one or more bind variables. Use the "using" clause to bind them in the execute immediate.
create or replace table some_table(message string);
execute immediate $$
declare
rs resultset;
select_statement string;
ins string default 'INSERT INTO SOME_TABLE(MESSAGE) values (?)';
begin
select_statement := 'Some text';
rs := (execute immediate :ins using (select_statement));
return table(rs);
exception
when statement_error then
return object_construct('Error type', 'STATEMENT_ERROR',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
when other then
return object_construct('Error type', 'Other error',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
end;
$$
;
The return of the table is optional, but helps with the return for programmatic access or human readability.
number of rows inserted
1

ORACLE : renaming a key in a json field by oracle

I have a table in which in one of the columns there is a json data as below
COLUMN NAME : JSON_CODE
{
"DataElaborazione" : "20220718",
"DataMovimento" : "20220531",
"DataRiferimento" : "20220715",
}
I want to rename DataRiferimento to datarif
expected result
COLUMN NAME : JSON_CODE
{
"DataElaborazione" : "20220718",
"DataMovimento" : "20220531",
"datarif" : "20220715",
}
see image for structure
thank you
You can use JSON_TRANSFORM function:
select JSON_TRANSFORM('{ "DataElaborazione" : "20220718", "DataMovimento" : "20220531", "DataRiferimento" : "20220715" }',
RENAME '$.DataRiferimento' = 'datarif')
from dual
Or JSON_OBJECT_T:
declare
v_json JSON_OBJECT_T;
begin
v_json := JSON_OBJECT_T('{ "DataElaborazione" : "20220718", "DataMovimento" : "20220531", "DataRiferimento" : "20220715" }');
v_json.rename_key('DataRiferimento', 'datarif');
dbms_output.put_line(v_json.stringify);
end;
You can create function and use it in your query:
create or replace function renameJsonKey(p_json IN VARCHAR2,
p_old_key IN VARCHAR2,
p_new_key IN VARCHAR2) return VARCHAR2
RESULT_CACHE RELIES_ON (your_table)
is
v_json JSON_OBJECT_T;
begin
v_json := JSON_OBJECT_T(p_json);
v_json.rename_key(p_old_key, p_new_key);
return v_json.stringify;
end;
select renameJsonKey(col, 'DataRiferimento', 'datarif') from your table

How to merge two jsonb objects in Postgres?

I have function where I select common fields for task, I have task_type and I need to select different fields by task_type and then return Json. I don't know SQL and Postgres tricks. Please give me hint! thanks
This is my Idea:
CREATE OR REPLACE FUNCTION crm.task_select(_task_uid bigint)
RETURNS jsonb
LANGUAGE plpgsql
AS $function$
DECLARE
_data jsonb;
_task jsonb;
begin
SELECT
task.task_uid AS "id",
task.action_date,
task.descrtiption,
sub.subject_data,
dtask.task_type,
dtask.name AS "task_name",
dtask.label AS "task_label",
lbadmin.user_name_reverse(crea) AS "created_by",
lbadmin.user_name_reverse(upda) AS "updated_by",
task.created,
task.updated,
case when dtask.task_type == 'email'
_task = select crm.selectEmail(task_uid);
end;
FROM crm.tasks "task"
LEFT JOIN abook2.subjects "sub" ON (task.subject_uid = sub.subject_uid)
LEFT JOIN crm.def_tasks "dtask" ON (task.def_task_uid = dtask.def_task_uid)
LEFT JOIN lbadmin.users_user "crea" ON (task.insert_user_uid = crea.role_uid)
LEFT JOIN lbadmin.users_user "upda" ON (task.update_user_uid = upda.role_uid)
LEFT JOIN crm.emails "email" ON (task.email_uid = email.email_uid)
WHERE
(task.task_uid = _task_uid)
AND (task.org_uid IS NULL)
AND (task.card_uid IS NULL) into _data;
_data = _task + _data;
return _data;
END;
$function$
Solution that helped me to get array of json objects:
select to_json(array_agg(row_to_json(t)))
from (select typ,prop from bgb where id=b.id) t )```

Cannot find ID , but really exists in Postgres

I am trying to pull data from a database to create a progress board fro some this query keeps returning for output."Data", even for values of projectId that actually exist in DB, project_id is an id that is inputted into the function.
-- FUNCTION: "ProjectProgress"."GetStepStatusbyProject"("Common"."InputDBMessage")
-- DROP FUNCTION "ProjectProgress"."GetStepStatusbyProject"("Common"."InputDBMessage");
CREATE OR REPLACE FUNCTION "ProjectProgress"."GetStepStatusbyProject"(
userinput "Common"."InputDBMessage")
RETURNS "Common"."OutputDBMessage"
LANGUAGE "plpgsql"
COST 100
VOLATILE
AS $BODY$
-- History:
-- 04/24/2020 Nick: Created Function
DECLARE
status_info jsonb;
input_params jsonb;
project_id bigint;
project_exists bool = true;
output "Common"."OutputDBMessage";
BEGIN
input_params := userinput."Parameters";
project_id := input_params ->> 'Id';
PERFORM "Log"."LogBeginRoutine"(userinput."UserName", userinput."ApplicationName", 'StepStatuses', 'GetStepStatusbyProject', userinput."ClientId", userinput."SessionId");
SELECT INTO project_exists (EXISTS(SELECT * FROM "LIMS"."Projects" WHERE "Id" = project_id));
IF NOT project_exists THEN
output."ErrorCode" = 1;
output."UserMessage" = 'project_id id not found';
ELSE
SELECT
array_to_json(array_agg(( ss.*, st."Color",st."Description",st."Icon"))) INTO status_info
FROM "LIMS"."Projects" as pr INNER JOIN "ProjectProgress"."Steps" as s
ON s."ProjectId" = pr."Id"
INNER JOIN (
SELECT
stepstatus.*
FROM
"ProjectProgress"."StepStatuses" AS stepstatus INNER JOIN
(
SELECT
MAX("Id") m_id, "StepId"
FROM
"ProjectProgress"."StepStatuses"
GROUP BY "StepId"
) AS mss ON mss.m_id = stepstatus."Id"
) as ss
ON ss."StepId" = s."Id"
INNER JOIN "ProjectProgress"."StatusTemplates" as st
ON ss."StatusTemplateId" = st."Id"
WHERE
st."Description" != 'Not Started' AND pr."Id" = project_id;
output."Data" := status_info;
output."ErrorCode" := 0;
output."UserMessage" := 'status successfully retrieved.';
PERFORM "Log"."LogEndSuccessRoutine"(userinput."UserName", userinput."ApplicationName", 'StepStatuses', 'GetStepStatusbyProject', userinput."ClientId", userinput."SessionId");
return output;
END
$BODY$;

SQL stored procedure compile error: wrong number or types of arguments in call

I have created this stored procedure. However I get this error
ORA-06550:line 14 column 3: PLS-00306:
wrong number or types of arguments in
call to 'CHALLENGEUPDATE' when the
values passed are CUSTID
:='400800500' ; POLICYNAME :=
'POLICY'; CHALLENGEID :=
'CHALLENGEID1'; PINPOSITIONS :=
'PINPOS';
The code is:
create or replace
procedure ChallengeUpdate
(
CustID IN SEC_CHALLENGE.CUSTOMERID%TYPE,
PolicyName IN SEC_CHALLENGE.POLICY_NAME%TYPE,
ChallengeId IN SEC_CHALLENGE.CHALLENGE_ID%TYPE,
PinPositions IN SEC_CHALLENGE.PINPOSITIONS%TYPE,
o_result OUT INTEGER,
o_code OUT INTEGER,
o_c OUT INTEGER
)
as
c integer;
begin
select count(*) into c from SEC_CHALLENGE xyz where xyz.CUSTOMERID=CustID and
xyz.POLICY_NAME=PolicyName;
if c = 0 then
INSERT INTO SEC_CHALLENGE(CUSTOMERID,CHALLENGE_ID,PINPOSITIONS,POLICY_NAME)
VALUES (CustID,ChallengeId, PinPositions, PolicyName);
else
UPDATE RBSSEC_CHALLENGE
SET CHALLENGE_ID=ChallengeId, PINPOSITIONS=PinPositions
WHERE CUSTOMERID=CustID and POLICY_NAME = PolicyName;
end if;
commit;
o_result:=0;
o_c:=c;
exception when others then
o_result:=-1;
o_c:=c;
rollback;
o_code :=SQLCODE;
end ChallengeUpdate;
The SEC_CHALLENGE table is this
CREATE TABLE "MUJEEB"."RBSSEC_CHALLENGE"
(
"CUSTOMERID" VARCHAR2(9 BYTE) NOT NULL ENABLE,
"CHALLENGE_ID" VARCHAR2(50 BYTE),
"PINPOSITIONS" VARCHAR2(20 BYTE) NOT NULL ENABLE,
"POLICY_NAME" VARCHAR2(50 BYTE) NOT NULL ENABLE,
CONSTRAINT "RBSSEC_CHALLENGE1_PK" PRIMARY KEY ("CHALLENGE_ID")
)
here is how I am running it:
DECLARE CUSTID VARCHAR2(9);
POLICYNAME VARCHAR2(50);
CHALLENGEID VARCHAR2(50);
PINPOSITIONS VARCHAR2(20);
O_RESULT NUMBER;
O_CODE NUMBER;
BEGIN CUSTID :='400800500' ;
POLICYNAME := 'POLICY';
CHALLENGEID := 'CHALLENGEID1';
PINPOSITIONS := 'PINPOS';
CHALLENGEUPDATE( CUSTID => CUSTID, POLICYNAME => POLICYNAME, CHALLENGEID => CHALLENGEID, PINPOSITIONS => PINPOSITIONS, O_RESULT => O_RESULT, O_CODE => O_CODE );
DBMS_OUTPUT.PUT_LINE('O_RESULT = ' || O_RESULT);
DBMS_OUTPUT.PUT_LINE('O_CODE = ' || O_CODE);
END;
If you use output parameters, marked with the "out" keyword, you must pass a variable for that parameter. Output params are not optional. From the error, I gather that you have not done so.
if you are using toad, try it this way:
var o_result integer;
var ocode integer;
var oc integer;
exec ChallengeUpdate ('400800500', 'POLICY', 'CHALLENGEID1', 'PINPOS', :o_result, :ocode, :oc );
print o_result;
print ocode ;
print oc;
From the declaration:
procedure ChallengeUpdate
(
CustID IN SEC_CHALLENGE.CUSTOMERID%TYPE,
PolicyName IN SEC_CHALLENGE.POLICY_NAME%TYPE,
ChallengeId IN SEC_CHALLENGE.CHALLENGE_ID%TYPE,
PinPositions IN SEC_CHALLENGE.PINPOSITIONS%TYPE,
o_result OUT INTEGER,
o_code OUT INTEGER,
o_c OUT INTEGER
) as
Your call to CHALLENGEUPDATE happens to miss an output variable for o_c OUT INTEGER. You may try the bellow:
exec CHALLENGEUPDATE(
CUSTID => CUSTID
, POLICYNAME => POLICYNAME
, CHALLENGEID => CHALLENGEID
, PINPOSITIONS => PINPOSITIONS
, O_RESULT => O_RESULT
, O_CODE => O_CODE
, O_C => O_C_tobedeclared);