File: v21-dem-identity-dynamic.sql

package info (click to toggle)
gnumed-server 22.31-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 46,268 kB
  • sloc: sql: 1,217,633; python: 15,878; sh: 1,590; makefile: 20
file content (146 lines) | stat: -rw-r--r-- 4,082 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
-- ==============================================================
-- GNUmed database schema change script
--
-- License: GPL v2 or later
-- Author: karsten.hilbert@gmx.net
--
-- ==============================================================
\set ON_ERROR_STOP 1
--set default_transaction_read_only to off;

set check_function_bodies to on;

-- --------------------------------------------------------------
comment on column dem.identity.comment is
	'A free-text comment on this identity.\n
\n
Can be used to to discriminate patients which are otherwise\n
identical regarding name and date of birth.\n
Should be something non-ephemereal and unique to the person\n
itself across time, place and database instance.\n
Good: place of birth\n
Good: maiden name of mother\n
Good: mother of <name>\n
Good: hash of DNA\n
Good (?): hair color of first pet\n
Bad: current address (will change)\n
Bad: primary provider in this praxis (can change, invalid in another GNUmed instance)\n
Bad: nickname (will change, can dupe as well)\n
Bad: favourite food\n
not-quite-so-bad: occupation';

-- --------------------------------------------------------------
drop function if exists dem.new_pupic() cascade;

-- --------------------------------------------------------------
drop function if exists dem.trf_sane_identity_comment() cascade;

-- disable audit trigger for update (because table layout has changed)
alter table dem.identity
	disable trigger zt_upd_identity;

-- de-duplicate
update dem.identity set
	comment = coalesce(comment, '') || '[auto-set by <v21-dem-identity-dynamic.sql>: ' || clock_timestamp() || ']'
where
	pk in (
		select pk_identity
		from dem.v_persons d_vp1
		where exists (
			select 1 from dem.v_persons d_vp2
			where
				d_vp2.firstnames = d_vp1.firstnames
					and
				d_vp2.lastnames = d_vp1.lastnames
					and
				d_vp2.gender = d_vp1.gender
					and
				date_trunc('day', d_vp2.dob) = date_trunc('day', d_vp1.dob)
					and
				d_vp2.pk_identity != d_vp1.pk_identity
		)
	)
;


-- create function and trigger
create function clin.trf_sane_identity_comment()
	returns trigger
	language 'plpgsql'
	as '
DECLARE
	_identity_row record;
	_names_row record;
BEGIN
	if TG_TABLE_NAME = ''identity'' then
		if TG_OP = ''UPDATE'' then
			if NEW.comment IS NOT DISTINCT FROM OLD.comment then
				return NEW;
			end if;
		end if;
		_identity_row := NEW;
		select * into _names_row from dem.names where id_identity = NEW.pk;
	else
		select * into _identity_row from dem.identity where pk = NEW.id_identity;
		_names_row := NEW;
	end if;

	-- any row with
	PERFORM 1 FROM
		dem.v_all_persons
	WHERE
		-- same firstname
		firstnames = _names_row.firstnames
			and
		-- same lastname
		lastnames = _names_row.lastnames
			and
		-- same gender
		gender is not distinct from _identity_row.gender
			and
		-- same dob (day)
		dob_only is not distinct from _identity_row.dob
			and
		-- same discriminator
		comment is not distinct from _identity_row.comment
			and
		-- but not the currently updated or inserted row
		pk_identity != _identity_row.pk
	;
	if FOUND then
		RAISE EXCEPTION
			''% on %.%: More than one person with (firstnames=%), (lastnames=%), (dob=%), (comment=%)'',
				TG_OP,
				TG_TABLE_SCHEMA,
				TG_TABLE_NAME,
				_names_row.firstnames,
				_names_row.lastnames,
				_identity_row.dob,
				_identity_row.comment
			USING ERRCODE = ''unique_violation''
		;
		RETURN NULL;
	end if;

	return NEW;
END;';

comment on function clin.trf_sane_identity_comment() is
	'Ensures unique(identity.dob, names.firstnames, names.lastnames, identity.comment)';


create trigger tr_sane_identity_comment
	after insert or update on dem.identity
	for each row execute procedure clin.trf_sane_identity_comment();


create trigger tr_sane_identity_comment
	after insert or update on dem.names
	for each row execute procedure clin.trf_sane_identity_comment();


-- tob nullable
-- dob = (dyob + coalesce(tob, 11:11:11.111)) at client_timezone

-- --------------------------------------------------------------
select gm.log_script_insertion('v21-dem-identity-dynamic.sql', '21.0');