Unexpected behavior in returning composite type for plpgsql function - plpgsql

So, I'm stuck with some issue on plpgsql, and I don't know what I may be doing wrong. I created a composite type, which I use as return in a plpgsql function, for obtaining it in another. The problem is that this doesn't behave the way I expected.
Here's my composite type:
CREATE TYPE sync.sync_conn_data AS (
sync_conn_name VARCHAR,
sync_active BOOLEAN,
sync_use_ssl BOOLEAN,
lcl_ctry VARCHAR,
lcl_dbhostaddr VARCHAR,
lcl_dbname VARCHAR,
lcl_dbuser VARCHAR,
lcl_dbpasswd VARCHAR,
rmte_ctry VARCHAR,
rmte_dbhostaddr VARCHAR,
rmte_dbname VARCHAR,
rmte_dbuser VARCHAR,
rmte_dbpasswd VARCHAR,
timezone VARCHAR
);
Here's the function that returns it:
CREATE OR REPLACE FUNCTION sync.sync_connect (
param_name VARCHAR = 'sync_db'::VARCHAR
)
RETURNS sync.sync_conn_data AS
$body$
DECLARE
sync_connrcd sync.sync_conn_data;
BEGIN
WITH all_conn_prms AS (
SELECT (CASE WHEN param_name = 'local_country' THEN param_value ELSE NULL END) AS local_country,
(CASE WHEN param_name = 'sync_active' THEN param_value ELSE NULL END) AS sync_active,
(CASE WHEN param_name = 'sync_use_ssl' THEN param_value ELSE NULL END) AS sync_use_ssl,
(CASE WHEN param_name = 'ago_dbhostaddr' THEN param_value ELSE NULL END) AS ago_dbhostaddr,
(CASE WHEN param_name = 'ago_dbname' THEN param_value ELSE NULL END) AS ago_dbname,
(CASE WHEN param_name = 'ago_dbuser' THEN param_value ELSE NULL END) AS ago_dbuser,
(CASE WHEN param_name = 'ago_dbpasswd' THEN param_value ELSE NULL END) AS ago_dbpasswd,
(CASE WHEN param_name = 'cub_dbhostaddr' THEN param_value ELSE NULL END) AS cub_dbhostaddr,
(CASE WHEN param_name = 'cub_dbname' THEN param_value ELSE NULL END) AS cub_dbname,
(CASE WHEN param_name = 'cub_dbuser' THEN param_value ELSE NULL END) AS cub_dbuser,
(CASE WHEN param_name = 'cub_dbpasswd' THEN param_value ELSE NULL END) AS cub_dbpasswd
FROM sync.sync_config_params
WHERE param_name IN ('local_country','sync_active','sync_use_ssl','ago_dbhostaddr','ago_dbname','ago_dbuser','ago_dbpasswd','cub_dbhostaddr','cub_dbname','cub_dbuser','cub_dbpasswd')
),
fltd_conn_prms AS (
SELECT string_agg(all_conn_prms.local_country, ',') AS local_country,
string_agg(all_conn_prms.sync_active, ',') AS sync_active,
string_agg(all_conn_prms.sync_use_ssl, ',') AS sync_use_ssl,
string_agg(all_conn_prms.ago_dbhostaddr, ',') AS ago_dbhostaddr,
string_agg(all_conn_prms.ago_dbname, ',') AS ago_dbname,
string_agg(all_conn_prms.ago_dbuser, ',') AS ago_dbuser,
string_agg(all_conn_prms.ago_dbpasswd, ',') AS ago_dbpasswd,
string_agg(all_conn_prms.cub_dbhostaddr, ',') AS cub_dbhostaddr,
string_agg(all_conn_prms.cub_dbname, ',') AS cub_dbname,
string_agg(all_conn_prms.cub_dbuser, ',') AS cub_dbuser,
string_agg(all_conn_prms.cub_dbpasswd, ',') AS cub_dbpasswd
FROM all_conn_prms
)
SELECT coalesce(sync_conn_name, 'sync_db') AS sync_conn_name,
fltd_conn_prms.sync_active,
fltd_conn_prms.sync_use_ssl,
fltd_conn_prms.local_country AS lcl_ctry,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.ago_dbhostaddr WHEN 'CUB' THEN fltd_conn_prms.cub_dbhostaddr ELSE NULL END) AS lcl_dbhostaddr,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.ago_dbname WHEN 'CUB' THEN fltd_conn_prms.cub_dbname ELSE NULL END) AS lcl_dbname,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.ago_dbuser WHEN 'CUB' THEN fltd_conn_prms.cub_dbuser ELSE NULL END) AS lcl_dbuser,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.ago_dbpasswd WHEN 'CUB' THEN fltd_conn_prms.cub_dbpasswd ELSE NULL END) AS lcl_dbpasswd,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN 'CUB' WHEN 'CUB' THEN 'AGO' ELSE NULL END) AS rmte_ctry,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.cub_dbhostaddr WHEN 'CUB' THEN fltd_conn_prms.ago_dbhostaddr ELSE NULL END) AS rmte_dbhostaddr,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.cub_dbname WHEN 'CUB' THEN fltd_conn_prms.ago_dbname ELSE NULL END) AS rmte_dbname,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.cub_dbuser WHEN 'CUB' THEN fltd_conn_prms.ago_dbuser ELSE NULL END) AS rmte_dbuser,
(CASE fltd_conn_prms.local_country WHEN 'AGO' THEN fltd_conn_prms.cub_dbpasswd WHEN 'CUB' THEN fltd_conn_prms.ago_dbpasswd ELSE NULL END) AS rmte_dbpasswd,
current_setting('TIMEZONE') AS timezone
INTO sync_connrcd
FROM fltd_conn_prms;
IF NOT FOUND THEN
RAISE EXCEPTION 'Exception text...';
END IF;
RETURN sync_connrcd;
EXCEPTION
WHEN others THEN
RAISE NOTICE 'SQLERRM -> %', quote_nullable(SQLERRM);
INSERT INTO sync.sync_exec_log (log_type, log_msg) VALUES (1, SQLERRM);
RETURN sync_connrcd;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
And here's the function where I expect the result:
CREATE OR REPLACE FUNCTION sync.validate_config (
// input params...
)
RETURNS pg_catalog.void AS
$body$
DECLARE
conn_data sync.sync_conn_data;
// ...
BEGIN
SELECT sync.sync_connect('sync_cfg_mgmt') INTO conn_data;
IF conn_data.lcl_ctry IS NULL OR conn_data.lcl_dbname IS NULL OR conn_data.lcl_dbhostaddr IS NULL OR conn_data.lcl_dbuser IS NULL OR conn_data.lcl_dbpasswd IS NULL OR conn_data.rmte_ctry IS NULL OR conn_data.rmte_dbname IS NULL OR conn_data.rmte_dbhostaddr IS NULL OR conn_data.rmte_dbuser IS NULL OR conn_data.rmte_dbpasswd IS NULL THEN
RAISE EXCEPTION 'No data obtained';
END IF;
// more code ...
EXCEPTION
WHEN others THEN
RAISE NOTICE 'SQLERRM -> %', quote_nullable(SQLERRM);
INSERT INTO sync.sync_exec_log (log_type, log_msg) VALUES (1, quote_nullable(SQLERRM));
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
The funny fact is that, using the EMS SQL Manager for PostgreSQL for debugging, this code works perfectly, but when executed the function sync.validate_config() through any client, throws the exception of no data obtained, 'cause all the fields in the conn_data object are null, except for the first one, which contains all the object info. This is the output I get when putting this multiple RAISE NOTICE after getting the result in the function:
RAISE NOTICE '%', conn_data.sync_conn_name;
RAISE NOTICE '%', conn_data.sync_active;
RAISE NOTICE '%', conn_data.sync_use_ssl;
RAISE NOTICE '%', conn_data.lcl_ctry;
RAISE NOTICE '%', conn_data.lcl_dbhostaddr;
RAISE NOTICE '%', conn_data.lcl_dbname;
RAISE NOTICE '%', conn_data.lcl_dbuser;
RAISE NOTICE '%', conn_data.lcl_dbpasswd;
RAISE NOTICE '%', conn_data.rmte_ctry;
RAISE NOTICE '%', conn_data.rmte_dbhostaddr;
RAISE NOTICE '%', conn_data.rmte_dbname;
RAISE NOTICE '%', conn_data.rmte_dbuser;
RAISE NOTICE '%', conn_data.rmte_dbpasswd;
RAISE NOTICE '%', conn_data.timezone;
Please, does anyone knows what's happening here?
Thanks in advance.

Since nobody answered my question, and I was in a little hurry, I looked for alternatives to solve this problem. I share now the solution I found, in case anyone else has had this kind of problem.
I used de plpgsql hstore module for the returning type of the sync.sync_connect() function, in this way:
CREATE OR REPLACE FUNCTION sync.sync_connect (
sync_conn_name VARCHAR = 'sync_db'::VARCHAR
)
RETURNS hstore AS
$body$
DECLARE
sync_connrcd sync.sync_conn_data;
BEGIN
/* Same code as before, where sync_connrcd is filled */
RAISE NOTICE 'conn_data -> %', row_to_json(sync_connrcd);
RETURN hstore(sync_connrcd);
EXCEPTION
WHEN others THEN
RAISE NOTICE 'SQLERRM -> %', quote_nullable(SQLERRM);
INSERT INTO sync.sync_exec_log (log_type, log_msg) VALUES (1, SQLERRM);
RETURN hstore(sync_connrcd);
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
And then, in the sync.validate_config() function I stored the result into an hstore object, this way:
CREATE OR REPLACE FUNCTION sync.validate_config (
/* input params */
)
RETURNS pg_catalog.void AS
$body$
DECLARE
conn_data hstore;
/* more variables */
BEGIN
SELECT sync.sync_connect('sync_cfg_mgmt') INTO conn_data;
IF NOT exist(conn_data, 'lcl_ctry') OR NOT defined(conn_data, 'lcl_ctry') OR
NOT exist(conn_data, 'lcl_dbname') OR NOT defined(conn_data, 'lcl_dbname') OR
NOT exist(conn_data, 'lcl_dbhostaddr') OR NOT defined(conn_data, 'lcl_dbhostaddr') OR
NOT exist(conn_data, 'lcl_dbuser') OR NOT defined(conn_data, 'lcl_dbuser') OR
NOT exist(conn_data, 'lcl_dbpasswd') OR NOT defined(conn_data, 'lcl_dbpasswd') OR
NOT exist(conn_data, 'rmte_ctry') OR NOT defined(conn_data, 'rmte_ctry') OR
NOT exist(conn_data, 'rmte_dbname') OR NOT defined(conn_data, 'rmte_dbname') OR
NOT exist(conn_data, 'rmte_dbhostaddr') OR NOT defined(conn_data, 'rmte_dbhostaddr') OR
NOT exist(conn_data, 'rmte_dbuser') OR NOT defined(conn_data, 'rmte_dbuser') OR
NOT exist(conn_data, 'rmte_dbpasswd') OR NOT defined(conn_data, 'rmte_dbpasswd') THEN
RAISE EXCEPTION 'No data obtained';
END IF;
/* more code */
EXCEPTION
WHEN others THEN
RAISE NOTICE 'SQLERRM -> %', quote_nullable(SQLERRM);
INSERT INTO sync.sync_exec_log (log_type, log_msg) VALUES (1, SQLERRM);
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
And to access any of the values within the object, I do it as follows conn_data->'rmte_dbname'.
That's all, it works perfectly fine for me.

Related

Checking Function Parameter Postgres

i'm trying to find the fastest way to check whether my postgres function parameter is null or empty.
my current function looks like:
CREATE OR REPLATE FUNCTON update_seller_detail(seller_id int,
seller_name varchar, seller_address varchar, seller_gender varchar)
RETURNS character varying
LANGUAGE plpsql
SECURITY DEFINER
AS $function$
BEGIN
IF seller_id = '' THEN
RAISE NOTICE 'Check Parameter'
return -1
ELSE
IF seller_name = '' THEN
UPDATE seller SET address=seller_address, gender=seller_gender WHERE id=seller_id;
ELSEIF seller_address = '' THEN
UPDATE seller SET name=seller_name, gender=seller_gender WHERE id=seller_id;
ELSE seller_gender= '' THEN
UPDATE seller SET name=seller_name, address=seller_address WHERE id=seller_id;
END IF;
END IF;
END;
$function$
Is there any way to find which of the parameter is null? so i can set my update to the column that's not null. thanks
you can use coalesce(nullif(trim(<column-reference>), '') in update query with column reference:
CREATE OR REPLACE FUNCTION update_seller_detail(
seller_id int,
seller_name varchar,
seller_address varchar,
seller_gender varchar
)
RETURNS character varying
LANGUAGE plpgsql
SECURITY DEFINER
AS
$function$
BEGIN
IF seller_id ISNULL THEN
RAISE NOTICE 'Check Parameter';
return -1;
ELSE
UPDATE public.seller s
SET name = coalesce(nullif(trim(seller_name), ''), s.name),
address = coalesce(nullif(trim(seller_address), ''), s.address),
gender = coalesce(nullif(trim(seller_gender), ''), s.gender)
WHERE id = seller_id;
return 1;
END IF;
END;
$function$

stack depth limit exceeded when fired a trigger

I am trying to build a slow changing dimensional table, it track all the history of records. The schema of the table is like this:
CREATE TABLE test.dim
(id text,
column1 text,
column2 text,
begin_date timestamp without time zone,
is_current boolean,
end_date timestamp without time zone)
I defined a trigger function, and fire it before each insert action:
CREATE OR REPLACE FUNCTION test.slow_change_func()
RETURNS trigger AS
$BODY$
DECLARE
BEGIN
IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim
WHERE id= NEW.id
AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null))
AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null))
AND is_current
)
)
THEN UPDATE yang_test.dim
SET (end_date, is_current) = (now(), FALSE)
WHERE id = NEW.id
AND is_current;
INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date)
VALUES ( NEW.id, NEW.column1, NEW.column2, now(), TRUE, 'infinity'::timestamp );
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
CREATE TRIGGER slow_change_trigger
BEFORE INSERT
ON test.dim
FOR EACH ROW
EXECUTE PROCEDURE test.slow_change_func();
When I try to test it,
INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date)
VALUES ( 1, 'hello', 'world', now(), TRUE, 'infinity'::timestamp )
it will throw an error: stack depth limit exceeded. it looks like the function is running a loop. any suggestion s?
I think I have figure this out, this will match my requirement:
CREATE OR REPLACE FUNCTION yang_test.slow_change_func()
RETURNS trigger AS
$BODY$
DECLARE
BEGIN
IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim
WHERE id= NEW.id
AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null))
AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null))
AND is_current
)
)
THEN UPDATE yang_test.dim
SET (end_date, is_current) = (now(), FALSE)
WHERE id = NEW.id
AND is_current;
ELSE RETURN null;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

PostgreSQL log trigger optimalization

I spent a lot of time trying to optimize our pgsql log trigger which started to be a problem. I did huge progress (from 18min to 2.5min by inserting 3M rows) but I would like to know if some pgSql masters will be able to do it even better.
CREATE OR REPLACE FUNCTION table_log_trig()
RETURNS trigger AS
$BODY$
DECLARE
col TEXT; -- Single column name to save
newVal TEXT; -- New value for column
oldVal TEXT; -- Old value for column
colLimit TEXT[]; -- Columns that should be logged
BEGIN
IF TG_ARGV[0] IS NOT NULL THEN
-- Trigger specifies columns to log
SELECT array_agg(unnest)
FROM unnest(string_to_array(TG_ARGV[0], ','))
INTO colLimit;
ELSE
-- Trigger with no params. Log all columns
SELECT array_agg(json_object_keys)
FROM json_object_keys(row_to_json(NEW))
WHERE json_object_keys NOT IN ('id', 'created_at', 'updated_at') -- Exceptions
INTO colLimit;
END IF;
-- Loop over columns that should be saved in log
FOREACH col IN ARRAY colLimit
LOOP
-- INSERT & UPDATE
EXECUTE 'SELECT ($1).' || col || '::text' INTO newVal USING NEW;
-- UPDATE
IF TG_OP = 'UPDATE' THEN
EXECUTE 'SELECT ($1).' || col || '::text' INTO oldVal USING OLD;
END iF;
-- Add only new or changed data
IF
newVal != oldVal OR
(oldVal IS NULL AND newVal IS NOT NULL) OR
(oldVal IS NOT NULL AND newVal IS NULL)
THEN
INSERT INTO tab_logs (record_id, field_name, old_value, new_value, created_at, created_by, action)
VALUES (NEW.id, col, oldVal, newVal, NOW(), 999, 'O');
END IF;
END LOOP;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
row_to_json() returns both column names and values; you may as well make use of these values, rather than extracting them later via dynamic SQL.
I haven't thoroughly tested this, let alone benchmarked it, but here's the gist of it:
CREATE OR REPLACE FUNCTION table_log_trig() RETURNS trigger AS
$$
DECLARE
OldJson JSONB = NULL;
BEGIN
IF TG_OP <> 'INSERT' THEN
OldJson := to_jsonb(old);
END IF;
INSERT INTO tab_logs (record_id, field_name, old_value, new_value, created_at, created_by, action)
SELECT new.id, key, OldValues.value, NewValues.value, now(), 999, 'O'
FROM jsonb_each(to_jsonb(new)) NewValues
LEFT JOIN jsonb_each(OldJson) OldValues USING (key)
WHERE
(
(TG_ARGV[0] IS NULL AND key NOT IN ('id', 'created_at', 'updated_at')) OR
(TG_ARGV[0] IS NOT NULL AND key = ANY(string_to_array(TG_ARGV[0], ',')))
) AND
OldValues.value::text IS DISTINCT FROM NewValues.value::text;
RETURN NULL;
END
$$
LANGUAGE plpgsql VOLATILE;

PostgreSQL: compare NULL and normal value

I have a trigger in PostgreSQL
CREATE OR REPLACE FUNCTION table_update_func_pk1() RETURNS trigger AS $$
DECLARE
ri RECORD;
old_value TEXT;
new_value TEXT;
BEGIN
FOR ri IN
SELECT column_name FROM information_schema.columns
WHERE
table_schema = quote_ident('public')
AND table_name = quote_ident(TG_TABLE_NAME)
ORDER BY ordinal_position
LOOP
EXECUTE 'SELECT ($1).' || ri.column_name || '::text' INTO new_value USING NEW;
EXECUTE 'SELECT ($1).' || ri.column_name || '::text' INTO old_value USING OLD;
IF new_value <> old_value AND ri.column_name != 'update_by' THEN
INSERT INTO protokoll(datetime, operation, tabelle, field, pk1, old_value, new_value, update_by)
VALUES(now(), TG_OP, TG_TABLE_NAME, ri.column_name, NEW.cfg, old_value, new_value, NEW.update_by);
END IF;
END LOOP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Sometimes if old_value is changed from NULL to normal value (or from normal value to NULL), the condition "new_value <> old_value" is NOT true but unknown. I would like ask, there is a method that I can get true in the case. Thanks.
Use is distinct from:
if new_value IS DISTINCT FROM old_value and ri.column_name <> 'update_by' then
...
end if;

2015-03-05 15:35:35 IST HINT No function matches the given name and argument types. You might need to add explicit type casts.

I have facing problem in the below function of postgres, I have tried by looking many examples like this, which has been uploaded by many others but still I dint find the solution. Please help me out.
I know the below function is lengthy. Thanks
CREATE OR REPLACE FUNCTION adt_transfer_patient(in_hospital_id integer, in_reg_no character varying(50), in_admt_id numeric, in_transfer_type character varying(25), in_release_cause character varying(1), in_user_id character varying(50), in_new_dept_id integer, in_new_unit_id integer, in_new_ward_id integer, in_consultant integer, in_icd character varying(50), in_icd_desc character varying(50))
RETURNS integer AS
$BODY$
DECLARE
temp_dept_id integer;
temp_unit_id integer;
temp_ward_id integer;
return_int integer;
temp_bed_id integer;
temp_present_position character varying;
temp_is_blocked integer;
max_diagnos_id integer;
tmp_bedno text;
tmp_ward text;
temp_node_ward_id integer;
tmp_tot_record integer;
tmp_int_var integer;
icdcode character varying(25);
disease_remark character varying(200);
BEGIN
temp_is_blocked=0;
--Present Department,Unit,Ward and Bed
SELECT dept_id INTO temp_dept_id FROM department_admission WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND release_date IS NULL ORDER BY admission_date DESC limit 1;
SELECT unit_id INTO temp_unit_id FROM unit_admission WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND release_date IS NULL;
SELECT ward_id INTO temp_ward_id FROM ward_admission WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND release_date IS NULL
ORDER BY admission_date DESC limit 1;
SELECT COALESCE(bedid,'0') INTO temp_bed_id FROM bed_occupancy WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND releasedate IS NULL;
--Tranfer Department
IF in_transfer_type = 'D' THEN
UPDATE department_admission SET release_date=current_timestamp,release_cause=in_release_cause,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND release_date IS NULL;
INSERT INTO department_admission(hospital_id,reg_no,ipd_admission_id,dept_id,admission_date,admission_time,userid)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_dept_id,current_timestamp,current_time,in_user_id);
END IF;
--Transfer Unit
IF in_transfer_type = 'D' OR in_transfer_type = 'U' THEN
UPDATE unit_admission SET release_date=current_timestamp,release_cause=in_release_cause,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND release_date IS NULL;
INSERT INTO unit_admission(hospital_id,reg_no,ipd_admission_id,unit_id,admission_date,admission_time,userid)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_unit_id,current_timestamp,current_time,in_user_id);
END IF;
--Transfer Ward
IF in_transfer_type = 'D' OR in_transfer_type = 'U' OR in_transfer_type = 'W' THEN
UPDATE ward_admission SET release_date=current_timestamp,release_cause=in_release_cause,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND release_date IS NULL;
IF in_transfer_type = 'W' THEN
INSERT INTO ward_admission(hospital_id,reg_no,ipd_admission_id,ward_id,admission_date,admission_time,userid,dept_id,unit_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_ward_id,current_timestamp,current_time,in_user_id,temp_dept_id,temp_unit_id);
ELSIF in_transfer_type = 'U' THEN
INSERT INTO ward_admission(hospital_id,reg_no,ipd_admission_id,ward_id,admission_date,admission_time,userid,dept_id,unit_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_ward_id,current_timestamp,current_time,in_user_id,temp_dept_id,in_new_unit_id);
ELSIF in_transfer_type = 'D' THEN
INSERT INTO ward_admission(hospital_id,reg_no,ipd_admission_id,ward_id,admission_date,admission_time,userid,dept_id,unit_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_ward_id,current_timestamp,current_time,in_user_id,in_new_dept_id,in_new_unit_id);
END IF;
END IF;
--Tranfer Bed
UPDATE bed_occupancy SET releasedate=current_timestamp,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND releasedate IS NULL;
--SELECT COUNT(*) into temp_is_blocked FROM mas_link_ward,ward_admission where mas_link_ward.parent_ward_id=ward_admission.ward_id
--and mas_link_ward.node_ward_id=temp_ward_id and ward_admission.release_date is null and abs(extract(epoch from current_timestamp - admission_date)/20000)>48;
-- SELECT COUNT(*) into temp_is_blocked FROM mas_link_ward,ward_admission where mas_link_ward.node_ward_id=ward_admission.ward_id and mas_link_ward.parent_ward_id=temp_ward_id and mas_link_ward.parent_dept_id=temp_dept_id and ward_admission.release_date is null and abs(extract(epoch from current_timestamp - admission_date)/20000)>48;
--SELECT node_ward_id into temp_node_ward_id FROM mas_link_ward,ward_admission where mas_link_ward.node_ward_id=ward_admission.ward_id and mas_link_ward.parent_ward_id=temp_ward_id and mas_link_ward.parent_dept_id=temp_dept_id and ward_admission.release_date is null and abs(extract(epoch from current_timestamp - admission_date)/20000)>48;
if temp_is_blocked is null then
temp_is_blocked=0;
end if;
IF temp_is_blocked>0 THEN
UPDATE mas_bed SET status='B' WHERE bedid=temp_bed_id AND hospital_id=in_hospital_id;
IF in_hospital_id=4 THEN
--*** insert record into notification table ***
select bedno into tmp_bedno from mas_bed where bedid=temp_bed_id;
select ward_name into tmp_ward from mas_ward where ward_id=temp_node_ward_id;
INSERT INTO table_notification(sl_no, notification, group_type, ward_id, dept_id, unit_id, employee_id,seen)
SELECT (SELECT COALESCE(max(sl_no),0) FROM table_notification)+row_number() OVER(),'Bed No'||tmp_bedno||' of ward '||tmp_ward||' is blocked','W',temp_node_ward_id,0,0,uid,0 FROM config.user_ward_mapping
WHERE ward_id=temp_node_ward_id;
END IF;
ELSE
UPDATE mas_bed SET status='A' WHERE bedid=temp_bed_id AND hospital_id=in_hospital_id;
END IF;
IF in_new_bed_id != 0 THEN
INSERT INTO bed_occupancy(hospital_id,reg_no,ipd_admission_id,bedid,occupancydate,occupied,userid,entrytime)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_bed_id,current_timestamp,'O',in_user_id,current_time);
UPDATE mas_bed SET status='O' WHERE bedid=in_new_bed_id AND hospital_id=in_hospital_id;
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,in_new_dept_id)||'^'||get_unit_name(in_hospital_id,in_new_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
END IF;
IF in_new_bed_id = 0 THEN
INSERT INTO bed_occupancy(hospital_id,reg_no,ipd_admission_id,bedid,occupancydate,occupied,userid,entrytime,transfer_to_floor)
VALUES (in_hospital_id,in_reg_no,in_admt_id,-1,current_timestamp,'O',in_user_id,current_time,'Y');
--UPDATE bed_occupancy SET transfer_to_floor='Y' WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id;
END IF;
--Entry in Patient transfer log
--NOTE: Valid Entry Against Trasnfer Type only
INSERT INTO patient_transfer_log(hospital_id, reg_no, ipd_admission_id, transfer_type, transfer_date,transfer_time, from_department_id, to_department_id, from_unit_id,
to_unit_id, from_ward_id, to_ward_id, from_bed_id, to_bed_id,consultant_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_transfer_type,current_timestamp,current_time,temp_dept_id,in_new_dept_id,temp_unit_id,
in_new_unit_id,temp_ward_id,in_new_ward_id,temp_bed_id,in_new_bed_id,in_consultant);
IF in_transfer_type = 'D' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,in_new_dept_id)||'^'||get_unit_name(in_hospital_id,in_new_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
ELSIF in_transfer_type = 'U' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,temp_dept_id)||'^'||get_unit_name(in_hospital_id,in_new_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
ELSIF in_transfer_type = 'W' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,temp_dept_id)||'^'||get_unit_name(in_hospital_id,temp_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
ELSIF in_transfer_type = 'B' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,temp_dept_id)||'^'||get_unit_name(in_hospital_id,temp_unit_id)||'^'||get_ward_name(in_hospital_id,temp_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
END IF;
UPDATE patient_detail SET present_position=COALESCE(present_position,' ^ ^ ^ ^')||temp_present_position,ward_id=in_new_ward_id,ward_entry_date=current_timestamp,bedid=in_new_bed_id,occupancydate=current_timestamp
WHERE reg_no=in_reg_no AND
hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id;
IF in_hospital_id=4 and in_icd<>'' THEN
select count(*) into tmp_tot_record from (select unnest(string_to_array(in_icd, ',')))tbl;
tmp_int_var = 1;
WHILE tmp_int_var <= tmp_tot_record LOOP
SELECT split_part(in_icd, ',', tmp_int_var) INTO icdcode;
SELECT split_part(in_icd_desc, ',', tmp_int_var) INTO disease_remark;
IF icdcode IS NOT NULL THEN
Select coalesce(max(slno),0)+1 into max_diagnos_id FROM tran_diagnosis_log where reg_no=in_reg_no;
INSERT INTO tran_diagnosis(
reg_no, slno,icd_o,remarks,
provisional_final, doctor_id, hospital_id, ipd_admission_no, entry_source,entry_date)
VALUES (in_reg_no, max_diagnos_id,icdcode,disease_remark,'Final', in_user_id::integer, in_hospital_id, in_admt_id,'TRANSFER',current_timestamp);
INSERT INTO tran_diagnosis_log(
reg_no, slno,icd_o,remarks,
provisional_final, doctor_id, hospital_id, ipd_admission_no, entry_source,entry_date)
VALUES (in_reg_no, max_diagnos_id,icdcode,disease_remark,'Final', in_user_id::integer, in_hospital_id, in_admt_id,'TRANSFER',current_timestamp);
tmp_int_var = tmp_int_var+1;
END IF;
END LOOP;
/**--update ipd_patient_admission_detail set disease=in_pro_diagnos where hospital_id=in_hospital_id and reg_no=in_reg_no and ipd_admission_id=in_admt_id;
Select coalesce(max(slno),0)+1 into max_diagnos_id FROM tran_diagnosis_log where reg_no=in_reg_no;
if max_diagnos_id=1 THEN
INSERT INTO tran_diagnosis(
reg_no, slno,
provisional_final, doctor_id, remarks, hospital_id, ipd_admission_no, entry_source)
VALUES (in_reg_no, max_diagnos_id,'Provisional', in_user_id::integer, in_pro_diagnos, in_hospital_id, in_admt_id,'TRANSFER');
INSERT INTO tran_diagnosis_log(
reg_no, slno,
provisional_final, doctor_id, remarks, hospital_id, ipd_admission_no, entry_source)
VALUES (in_reg_no, max_diagnos_id,'Provisional', in_user_id::integer, in_pro_diagnos, in_hospital_id, in_admt_id,'TRANSFER');
END IF;
if max_diagnos_id>1 THEN
INSERT INTO tran_diagnosis_log(
reg_no, slno,
provisional_final, doctor_id, remarks, hospital_id, ipd_admission_no, entry_source)
VALUES (in_reg_no, max_diagnos_id,'Provisional', in_user_id::integer, in_pro_diagnos, in_hospital_id, in_admt_id,'TRANSFER');
END IF; **/
END IF;
RETURN 1;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;