[med-svn] [Git][med-team/gnumed-server][upstream] New upstream version 22.28
Andreas Tille (@tille)
gitlab at salsa.debian.org
Sun Jan 28 17:07:08 GMT 2024
Andreas Tille pushed to branch upstream at Debian Med / gnumed-server
Commits:
9a9ffb0f by Andreas Tille at 2024-01-28T18:04:24+01:00
New upstream version 22.28
- - - - -
10 changed files:
- server/bootstrap/fixup_db-v22.conf
- server/bootstrap/update_db-v21_v22.conf
- server/doc/schema/gnumed-entire_schema.html
- server/gm-backup_and_zip_database.service
- server/gm-backup_and_zip_database.timer
- server/pycommon/gmBackendListener.py
- server/pycommon/gmConnectionPool.py
- server/pycommon/gmPG2.py
- server/sql/v21-v22/fixups/v22-gm-concat_table_structure_v19_and_up-fixup.sql
- server/sql/v21-v22/fixups/v22-release_notes-fixup.sql
Changes:
=====================================
server/bootstrap/fixup_db-v22.conf
=====================================
@@ -27,6 +27,7 @@ database alias = gnumed_v22
minimum postgresql version = 9.2
schema base directory = ../sql/v21-v22/fixups/
schema = $schema$
+v22-gm-concat_table_structure_v19_and_up-fixup.sql
v22-ref-paperwork_templates-fixups.sql
v22-invoice_id_grants-fixup.sql
v22-i18n-lang_funcs-fixup.sql
@@ -34,7 +35,6 @@ v22-clin-v_candidate_diagnoses-fixup.sql
v22-dem-v_message_inbox-fixup.sql
v22-add_generic_covid_vaccine.sql
v22-clin-remove_old_empty_encounters-fixup.sql
-v22-gm-concat_table_structure_v19_and_up-fixup.sql
v22-clin-move_waiting_list_entry-fixup.sql
v22-blobs-doc_med-idx.sql
v22-blobs-doc_obj-idx.sql
@@ -65,6 +65,7 @@ schema = $schema$
$schema$
superuser schema = $superuser schema$
+fixups/v22-gm-concat_table_structure_v19_and_up-fixup.sql
superuser/v22-gm-load_auto_explain.sql
$superuser schema$
=====================================
server/bootstrap/update_db-v21_v22.conf
=====================================
@@ -159,6 +159,7 @@ database alias = gnumed_v22
minimum postgresql version = 9.2
schema base directory = ../sql/v21-v22/fixups/
schema = $schema$
+v22-gm-concat_table_structure_v19_and_up-fixup.sql
v22-ref-paperwork_templates-fixups.sql
v22-invoice_id_grants-fixup.sql
v22-i18n-lang_funcs-fixup.sql
@@ -166,7 +167,6 @@ v22-clin-v_candidate_diagnoses-fixup.sql
v22-dem-v_message_inbox-fixup.sql
v22-add_generic_covid_vaccine.sql
v22-clin-remove_old_empty_encounters-fixup.sql
-v22-gm-concat_table_structure_v19_and_up-fixup.sql
v22-clin-move_waiting_list_entry-fixup.sql
v22-blobs-doc_med-idx.sql
v22-blobs-doc_obj-idx.sql
@@ -206,6 +206,7 @@ schema = $schema$
$schema$
superuser schema = $superuser schema$
+fixups/v22-gm-concat_table_structure_v19_and_up-fixup.sql
superuser/v22-gm-load_auto_explain.sql
$superuser schema$
=====================================
server/doc/schema/gnumed-entire_schema.html
=====================================
@@ -112,7 +112,7 @@
<body>
<!-- Primary Index -->
-<p><br><br>Dumped on 2023-12-25</p>
+<p><br><br>Dumped on 2024-01-28</p>
<h1><a name="index">Index of database - gnumed_v22</a></h1>
<ul>
@@ -158,7 +158,7 @@
<li><a name="gm.schema">gm</a></li><ul>
<li><a href="gnumed-entire_schema.html#gm.table.access-log">access_log</a></li><li><a href="gnumed-entire_schema.html#gm.table.notifying-tables">notifying_tables</a></li><li><a href="gnumed-entire_schema.html#gm.table.schema-revision">schema_revision</a></li>
- <li><a href="gnumed-entire_schema.html#gm.function.account-is-dbowner-or-staff-account-name">account_is_dbowner_or_staff(_account name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.add-missing-array-bits">add_missing_array_bits()</a></li><li><a href="gnumed-entire_schema.html#gm.function.add-table-for-notifies-name-name">add_table_for_notifies(name, name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.add-user-to-permission-group-name-name">add_user_to_permission_group(name, name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.array-unnest-anyarray">array_unnest(anyarray)</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure">concat_table_structure()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-integer">concat_table_structure(integer)</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v1">concat_table_structure_v1()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v16-and-up">concat_table_structure_v16_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v17-and-up">concat_table_structure_v17_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v18-and-up">concat_table_structure_v18_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v19-and-up">concat_table_structure_v19_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v2">concat_table_structure_v2()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v3">concat_table_structure_v3()</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-all-enc-epi-sanity-check-triggers">create_all_enc_epi_sanity_check_triggers()</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-all-table-mod-triggers-drop-old-triggers-boolean">create_all_table_mod_triggers(_drop_old_triggers boolean)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-enc-epi-sanity-check-trigger-schema-name-name-table-name-name-fk-encounter-col-name-fk-episode-col-name">create_enc_epi_sanity_check_trigger(_schema_name name, _table_name name, _fk_encounter_col name, _fk_episode_col name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-generic-combi-vaccine-text-textARRAY-text-boolean">create_generic_combi_vaccine(text, text[], text, boolean)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-table-mod-triggers-schema-name-name-table-name-name">create_table_mod_triggers(_schema_name name, _table_name name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-user-name-text">create_user(name, text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.disable-user-name">disable_user(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.drop-user-name">drop_user(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.get-users">get_users()</a></li><li><a href="gnumed-entire_schema.html#gm.function.get-users-name">get_users(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.is-null-or-blank-string-text">is_null_or_blank_string(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.is-null-or-non-empty-string-text">is_null_or_non_empty_string(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.lo-chunked-md5-oid-integer">lo_chunked_md5(oid, integer)</a></li><li><a href="gnumed-entire_schema.html#gm.function.log-access2emr-text">log_access2emr(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.log-other-access-text">log_other_access(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.log-script-insertion-text-text">log_script_insertion(text, text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.nullify-empty-string-text">nullify_empty_string(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.register-notifying-table-name-name">register_notifying_table(name, name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.strip-allzeros-fraction-numeric">strip_allzeros_fraction(numeric)</a></li><li><a href="gnumed-entire_schema.html#gm.function.transfer-users-text">transfer_users(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.transfer-users-text-text">transfer_users(text, text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.trf-announce-table-del">trf_announce_table_del()</a></li><li><a href="gnumed-entire_schema.html#gm.function.trf-announce-table-ins-upd">trf_announce_table_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#gm.function.user-exists-name">user_exists(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.xid2int-xid">xid2int(xid)</a></li>
+ <li><a href="gnumed-entire_schema.html#gm.function.account-is-dbowner-or-staff-account-name">account_is_dbowner_or_staff(_account name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.add-missing-array-bits">add_missing_array_bits()</a></li><li><a href="gnumed-entire_schema.html#gm.function.add-table-for-notifies-name-name">add_table_for_notifies(name, name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.add-user-to-permission-group-name-name">add_user_to_permission_group(name, name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.array-unnest-anyarray">array_unnest(anyarray)</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure">concat_table_structure()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-integer">concat_table_structure(integer)</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v1">concat_table_structure_v1()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v16-and-up">concat_table_structure_v16_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v17-and-up">concat_table_structure_v17_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v18-and-up">concat_table_structure_v18_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v19-and-up">concat_table_structure_v19_and_up()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v2">concat_table_structure_v2()</a></li><li><a href="gnumed-entire_schema.html#gm.function.concat-table-structure-v3">concat_table_structure_v3()</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-all-enc-epi-sanity-check-triggers">create_all_enc_epi_sanity_check_triggers()</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-all-table-mod-triggers-drop-old-triggers-boolean">create_all_table_mod_triggers(_drop_old_triggers boolean)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-enc-epi-sanity-check-trigger-schema-name-name-table-name-name-fk-encounter-col-name-fk-episode-col-name">create_enc_epi_sanity_check_trigger(_schema_name name, _table_name name, _fk_encounter_col name, _fk_episode_col name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-generic-combi-vaccine-text-textARRAY-text-boolean">create_generic_combi_vaccine(text, text[], text, boolean)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-table-mod-triggers-schema-name-name-table-name-name">create_table_mod_triggers(_schema_name name, _table_name name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.create-user-name-text">create_user(name, text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.disable-user-name">disable_user(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.drop-user-name">drop_user(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.get-users">get_users()</a></li><li><a href="gnumed-entire_schema.html#gm.function.get-users-name">get_users(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.is-null-or-blank-string-text">is_null_or_blank_string(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.is-null-or-non-empty-string-text">is_null_or_non_empty_string(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.lo-chunked-md5-oid-integer">lo_chunked_md5(oid, integer)</a></li><li><a href="gnumed-entire_schema.html#gm.function.load-auto-explain-min-duration-integer">load_auto_explain(_min_duration integer)</a></li><li><a href="gnumed-entire_schema.html#gm.function.log-access2emr-text">log_access2emr(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.log-other-access-text">log_other_access(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.log-script-insertion-text-text">log_script_insertion(text, text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.nullify-empty-string-text">nullify_empty_string(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.register-notifying-table-name-name">register_notifying_table(name, name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.strip-allzeros-fraction-numeric">strip_allzeros_fraction(numeric)</a></li><li><a href="gnumed-entire_schema.html#gm.function.transfer-users-text">transfer_users(text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.transfer-users-text-text">transfer_users(text, text)</a></li><li><a href="gnumed-entire_schema.html#gm.function.trf-announce-table-del">trf_announce_table_del()</a></li><li><a href="gnumed-entire_schema.html#gm.function.trf-announce-table-ins-upd">trf_announce_table_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#gm.function.user-exists-name">user_exists(name)</a></li><li><a href="gnumed-entire_schema.html#gm.function.xid2int-xid">xid2int(xid)</a></li>
</ul>
<li><a name="i18n.schema">i18n</a></li><ul>
@@ -129829,6 +129829,29 @@ BEGIN
return md5(_md5_concat);
END;</pre>
+<hr>
+<h2>Function:
+ <a href="gnumed-entire_schema.html#gm.schema">gm</a>.<a name="gm.function.load-auto-explain-min-duration-integer">load_auto_explain(_min_duration integer)</a>
+</h2>
+<h3>Returns: boolean</h3>
+<h3>Language: PLPGSQL</h3>
+<p>Load and configure auto_explain.
+.
+Integer argument = auto_explain.log_min_duration in milliseconds with a lower bound of 1500.</p>
+<pre>
+BEGIN
+ IF _min_duration < 1500 THEN
+ _min_duration := 1500;
+ END IF;
+ LOAD 'auto_explain';
+ PERFORM set_config('auto_explain.log_min_duration'::TEXT, _min_duration::TEXT, false);
+ PERFORM set_config('auto_explain.log_analyze'::TEXT, 'ON'::TEXT, false);
+ PERFORM set_config('auto_explain.log_verbose'::TEXT, 'ON'::TEXT, false);
+ PERFORM set_config('auto_explain.log_timing'::TEXT, 'ON'::TEXT, false);
+ PERFORM set_config('auto_explain.log_nested_statements'::TEXT, 'ON'::TEXT, false);
+ RETURN TRUE;
+END;</pre>
+
<hr>
<h2>Function:
<a href="gnumed-entire_schema.html#gm.schema">gm</a>.<a name="gm.function.log-access2emr-text">log_access2emr(text)</a>
=====================================
server/gm-backup_and_zip_database.service
=====================================
@@ -1,5 +1,7 @@
+# put into /usr/lib/systemd/system/
[Unit]
Description="GNUmed database backup service"
+Documentation=https://www.gnumed.de/documentation/
Requires=gm-backup_and_zip_database.timer
[Service]
=====================================
server/gm-backup_and_zip_database.timer
=====================================
@@ -1,3 +1,4 @@
+# put into /usr/lib/systemd/system/
[Unit]
Description="GNUmed database backup timer"
=====================================
server/pycommon/gmBackendListener.py
=====================================
@@ -35,13 +35,9 @@ class gmBackendListener(gmBorg.cBorg):
def __init__(self, conn=None, poll_interval:int=3):
- try:
- self.already_inited
+ if hasattr(self, 'already_inited'):
return
- except AttributeError:
- pass
-
#gmLog2.log_step(restart = True)
assert conn, '<conn> must be given'
@@ -429,6 +425,8 @@ if __name__ == "__main__":
print("shutting down backend notifications monitor")
#-------------------------------
+ gmPG2.request_login_params(setup_pool = True)
+
if sys.argv[1] == 'monitor':
run_monitor()
else:
=====================================
server/pycommon/gmConnectionPool.py
=====================================
@@ -706,6 +706,7 @@ def log_pg_exception_details(exc):
if not isinstance(exc, dbapi.Error):
return False
+ _log.error(type(exc))
try:
args = exc.args
for arg in args:
=====================================
server/pycommon/gmPG2.py
=====================================
@@ -55,9 +55,8 @@ except ImportError:
import psycopg2.errorcodes as sql_error_codes
import psycopg2.sql as psysql
-#import psycopg2.errors as PG_EXCEPTIONS
-PG_ERROR_EXCEPTION = dbapi.Error
+PG_ERROR_EXCEPTION = dbapi.DatabaseError
# =======================================================================
default_database = 'gnumed_v22'
@@ -374,8 +373,8 @@ def request_login_params(setup_pool=False):
# =======================================================================
# netadata API
# =======================================================================
-SQL__concat_table_structure_v19_and_up = """
-create or replace function gm.concat_table_structure_v19_and_up()
+SQL__pg_temp_concat_table_structure_v19_and_up = """
+create or replace function pg_temp.concat_table_structure_v19_and_up()
returns text
language 'plpgsql'
security definer
@@ -388,7 +387,6 @@ declare
_total text;
begin
_total := '''';
-
-- find relevant tables
for _table_desc in
select * from information_schema.tables tabs where
@@ -397,12 +395,10 @@ begin
tabs.table_type = ''BASE TABLE''
order by
decode(md5(tabs.table_schema || tabs.table_name), ''hex'')
-
-- loop over tables
loop
-- where are we at ?
- _total := _total || ''TABLE:'' || _table_desc.table_schema || ''.'' || _table_desc.table_name || E''\\n'';
-
+ _total := _total || ''TABLE:'' || _table_desc.table_schema || ''.'' || _table_desc.table_name || E''\n'';
-- find PKs of that table
for _pk_desc in
select * from (
@@ -426,7 +422,7 @@ begin
decode(md5(PKs.primary_key_column), ''hex'')
-- and loop over those PK columns
loop
- _total := _total || ''PK:'' || _pk_desc.primary_key_column || E''\\n'';
+ _total := _total || ''PK:'' || _pk_desc.primary_key_column || E''\n'';
end loop;
-- find columns of that table
@@ -446,10 +442,9 @@ begin
|| _column_desc.table_schema || ''.''
|| _column_desc.table_name || ''.''
|| _column_desc.column_name || ''::''
- || _column_desc.udt_name || E''\\n'';
+ || _column_desc.udt_name || E''\n'';
end loop;
-
-- find and loop over CONSTRAINTs of that table
for _constraint_def in
select * from
@@ -476,69 +471,158 @@ begin
CONSTRAINTs.contype,
decode(md5(CONSTRAINTs.condef), ''hex'')
loop
- _total := _total || _constraint_def.condef || E''\\n'';
+ _total := _total || _constraint_def.condef || E''\n'';
end loop;
-
end loop; -- over tables
-
return _total;
end;';
-
-select md5(gm.concat_table_structure(%(ver)s::integer)) AS md5;
"""
+SQL__get_pg_temp_table_structure = "select pg_temp.concat_table_structure_v19_and_up();"
+SQL__md5_pg_temp_table_structure = "select md5(pg_temp.concat_table_structure_v19_and_up()) AS md5;"
+#------------------------------------------------------------------------
def database_schema_compatible(link_obj=None, version=None, verbose=True):
expected_hash = known_schema_hashes[version]
- if version == 0:
- args = {'ver': 9999}
- else:
- args = {'ver': version}
- SQL = 'select md5(gm.concat_table_structure(%(ver)s::integer)) as md5'
- try:
- rows, idx = run_ro_queries(link_obj = link_obj, queries = [{'cmd': SQL, 'args': args}])
- except dbapi.errors.AmbiguousFunction as exc:
- gmConnectionPool.log_pg_exception_details(exc)
- if not hasattr(exc, 'diag'):
- raise
- if 'gm.concat_table_structure_v19_and_up()' not in exc.diag.context:
- raise
- rows = None
- if rows is None:
- _log.error('gm.concat_table_structure_v19_and_up() failed, retrying with updated function')
- rows, idx = run_ro_queries(link_obj = link_obj, queries = [{'cmd': SQL__concat_table_structure_v19_and_up, 'args': args}])
- if rows[0]['md5'] == expected_hash:
- _log.info('detected schema version [%s], hash [%s]' % (map_schema_hash2version[rows[0]['md5']], rows[0]['md5']))
+ ver = 9999 if version == 0 else version
+ md5_db = get_schema_hash(link_obj = link_obj, version = ver)
+ if md5_db == expected_hash:
+ _log.info('detected schema version [%s], hash [%s]' % (map_schema_hash2version[md5_db], md5_db))
return True
_log.error('database schema version mismatch')
_log.error('expected: %s (%s)' % (version, expected_hash))
- _log.error('detected: %s (%s)' % (get_schema_version(link_obj=link_obj), rows[0]['md5']))
+ try:
+ _log.error('detected: %s (%s)', map_schema_hash2version[md5_db], md5_db)
+ except KeyError:
+ _log.error('detected: <unknown> (%s)', md5_db)
if verbose:
- _log.debug('schema dump follows:')
- for line in get_schema_structure(link_obj = link_obj).split():
- _log.debug(line)
- _log.debug('schema revision history dump follows:')
- for line in get_schema_revision_history(link_obj = link_obj):
- _log.debug(' - '.join(line))
+ log_schema_structure(link_obj = link_obj)
+ log_schema_revision_history(link_obj = link_obj)
return False
#------------------------------------------------------------------------
def get_schema_version(link_obj=None):
- rows, idx = run_ro_queries(link_obj=link_obj, queries = [{'cmd': 'select md5(gm.concat_table_structure()) as md5'}])
+ md5_db = get_schema_hash(link_obj = link_obj)
+ if not md5_db:
+ _log.error('cannot determine schema version')
+ return None
+
try:
- return map_schema_hash2version[rows[0]['md5']]
+ return map_schema_hash2version[md5_db]
+
except KeyError:
- return 'unknown database schema version, MD5 hash is [%s]' % rows[0]['md5']
+ return 'unknown database schema version, MD5 hash is [%s]' % md5_db
+
+#------------------------------------------------------------------------
+def __get_schema_structure_by_gm_func(link_obj=None) -> str:
+ SQL = 'select gm.concat_table_structure()'
+ try:
+ rows, idx = run_ro_queries(link_obj=link_obj, queries = [{'cmd': SQL}])
+ return rows[0][0]
+
+ except dbapi.errors.AmbiguousFunction as exc:
+ if hasattr(exc, 'diag') and 'gm.concat_table_structure_v19_and_up()' in exc.diag.context:
+ _log.error('gm.concat_table_structure_v19_and_up() failed')
+ return None
+
+ gmConnectionPool.log_pg_exception_details(exc)
+ raise
+
+#------------------------------------------------------------------------
+def __get_schema_structure_by_pg_temp_func() -> str:
+ queries = [
+ {'cmd': SQL__pg_temp_concat_table_structure_v19_and_up},
+ {'cmd': SQL__get_pg_temp_table_structure}
+ ]
+ conn = get_connection(readonly = False)
+ try:
+ rows, idx = run_rw_queries(link_obj = conn, queries = queries, return_data = True)
+ return rows[0][0]
+
+ except PG_ERROR_EXCEPTION as exc:
+ _log.error('pg_temp.concat_table_structure_v19_and_up() failed')
+ gmConnectionPool.log_pg_exception_details(exc)
+ raise
+
+ finally:
+ conn.rollback()
+ conn.close()
+
+ # should never get here
+ return None
#------------------------------------------------------------------------
def get_schema_structure(link_obj=None):
- rows, idx = run_ro_queries(link_obj=link_obj, queries = [{'cmd': 'select gm.concat_table_structure()'}])
- return rows[0][0]
+ schema_struct = __get_schema_structure_by_gm_func(link_obj = link_obj)
+ if not schema_struct:
+ _log.debug('retrying with temporary function')
+ schema_struct = __get_schema_structure_by_pg_temp_func()
+ return schema_struct
#------------------------------------------------------------------------
-def get_schema_hash(link_obj=None):
- rows, idx = run_ro_queries(link_obj=link_obj, queries = [{'cmd': 'select md5(gm.concat_table_structure()) as md5'}])
- return rows[0]['md5']
+def log_schema_structure(link_obj=None):
+ _log.debug('schema structure dump:')
+ schema_struct = get_schema_structure(link_obj = link_obj)
+ if not schema_struct:
+ _log.error('cannot determine schema structure')
+ return
+
+ for line in schema_struct.split():
+ _log.debug(line)
+
+#------------------------------------------------------------------------
+def __get_schema_hash_by_gm_func(link_obj=None, version=None) -> str:
+ args = {}
+ if version:
+ SQL = 'SELECT md5(gm.concat_table_structure(%(ver)s::INTEGER)) AS md5'
+ args['ver'] = version
+ else:
+ SQL = 'SELECT md5(gm.concat_table_structure()) AS md5'
+ _log.debug('version: %s', version)
+ try:
+ rows, idx = run_ro_queries(link_obj=link_obj, queries = [{'cmd': SQL, 'args': args}])
+ _log.debug('hash: %s', rows[0]['md5'])
+ return rows[0]['md5']
+
+ except dbapi.errors.AmbiguousFunction as exc:
+ if hasattr(exc, 'diag') and 'gm.concat_table_structure_v19_and_up()' in exc.diag.context:
+ _log.error('gm.concat_table_structure_v19_and_up() failed')
+ return None
+
+ gmConnectionPool.log_pg_exception_details(exc)
+ raise
+
+#------------------------------------------------------------------------
+def __get_schema_hash_by_pg_temp_func() -> str:
+ conn = get_connection(readonly = False)
+ queries = [
+ {'cmd': SQL__pg_temp_concat_table_structure_v19_and_up},
+ {'cmd': SQL__md5_pg_temp_table_structure}
+ ]
+ try:
+ rows, idx = run_rw_queries(link_obj = conn, queries = queries, return_data = True)
+ _log.debug('hash: %s', rows[0]['md5'])
+ return rows[0]['md5']
+
+ except PG_ERROR_EXCEPTION as exc:
+ _log.error('pg_temp.concat_table_structure_v19_and_up() failed')
+ gmConnectionPool.log_pg_exception_details(exc)
+ raise
+
+ finally:
+ conn.rollback()
+ conn.close()
+
+ # should never get here
+ return None
+
+#------------------------------------------------------------------------
+def get_schema_hash(link_obj=None, version=None):
+ md5_db = __get_schema_hash_by_gm_func(link_obj = link_obj)
+ if not md5_db:
+ _log.debug('retrying with temporary function')
+ md5_db = __get_schema_hash_by_pg_temp_func()
+ return md5_db
#------------------------------------------------------------------------
def get_schema_revision_history(link_obj=None):
@@ -565,6 +649,12 @@ def get_schema_revision_history(link_obj=None):
rows, idx = run_ro_queries(link_obj = link_obj, queries = [{'cmd': cmd}])
return rows
+#------------------------------------------------------------------------
+def log_schema_revision_history(link_obj=None):
+ _log.debug('schema revision history dump:')
+ for line in get_schema_revision_history(link_obj = link_obj):
+ _log.debug(' - '.join(line))
+
#------------------------------------------------------------------------
def get_db_fingerprint(conn=None, fname=None, with_dump=False, eol=None):
queries = [
@@ -600,10 +690,7 @@ def get_db_fingerprint(conn=None, fname=None, with_dump=False, eol=None):
rows = curs.fetchall()
lines.append('%20s: %s' % ('Size (DB)', rows[0][0]))
# get hash
- cmd = "SELECT md5(gm.concat_table_structure())"
- curs.execute(cmd)
- rows = curs.fetchall()
- md5_sum = rows[0][0]
+ md5_sum = get_schema_hash(link_obj = curs)
try:
lines.append('%20s: %s (v%s)' % ('Schema hash', md5_sum, map_schema_hash2version[md5_sum]))
except KeyError:
@@ -613,10 +700,8 @@ def get_db_fingerprint(conn=None, fname=None, with_dump=False, eol=None):
rows = curs.fetchall()
lines.append('%20s: %s' % (label, rows[0][0]))
if with_dump:
- curs.execute('SELECT gm.concat_table_structure()')
- rows = curs.fetchall()
lines.append('')
- lines.append(rows[0][0])
+ lines.append(str(get_schema_structure(link_obj = curs)))
curs.close()
if fname is None:
if eol is None:
@@ -1755,7 +1840,7 @@ def run_ro_queries(link_obj=None, queries=None, verbose=False, return_data=True,
_log.exception('cannot rollback transaction')
gmConnectionPool.log_pg_exception_details(pg_exc2)
if pg_exc.pgcode == sql_error_codes.INSUFFICIENT_PRIVILEGE:
- details = 'Query: [%s]' % curs.query.strip().strip('\n').strip().strip('\n')
+ details = 'Query: [%s]' % curs.query.decode(errors = 'replace').strip().strip('\n').strip().strip('\n')
if curs.statusmessage != '':
details = 'Status: %s\n%s' % (
curs.statusmessage.strip().strip('\n').strip().strip('\n'),
@@ -1911,7 +1996,7 @@ def run_rw_queries(link_obj=None, queries=None, end_tx=False, return_data=None,
gmConnectionPool.log_pg_exception_details(pg_exc2)
# privilege problem
if pg_exc.pgcode == sql_error_codes.INSUFFICIENT_PRIVILEGE:
- details = 'Query: [%s]' % curs.query.strip().strip('\n').strip().strip('\n')
+ details = 'Query: [%s]' % curs.query.decode(errors = 'replace').strip().strip('\n').strip().strip('\n')
if curs.statusmessage != '':
details = 'Status: %s\n%s' % (
curs.statusmessage.strip().strip('\n').strip().strip('\n'),
@@ -2241,9 +2326,10 @@ if __name__ == "__main__":
if sys.argv[1] != 'test':
sys.exit()
- from Gnumed.pycommon.gmTools import file2md5
+ #from Gnumed.pycommon.gmTools import file2md5
logging.basicConfig(level=logging.DEBUG)
+ gmLog2.print_logfile_name()
#--------------------------------------------------------------------
def test_file2bytea():
@@ -2731,6 +2817,37 @@ SELECT to_timestamp (foofoo,'YYMMDD.HH24MI') FROM (
#print(get_db_fingerprint(conn, with_dump = True, eol = '\n'))
print(get_db_fingerprint(with_dump = True, eol = '\n'))
+ #--------------------------------------------------------------------
+ def test_schema_compatible():
+ request_login_params(setup_pool = True)
+ print(database_schema_compatible(version=22, verbose=True))
+
+ #--------------------------------------------------------------------
+ def test_get_schema_structure():
+ request_login_params(setup_pool = True)
+ print(get_schema_structure())
+
+ #--------------------------------------------------------------------
+ def test_pg_temp_concat():
+ request_login_params(setup_pool = True)
+ conn = get_connection(readonly = False)
+ queries = [
+ {'cmd': SQL__pg_temp_concat_table_structure_v19_and_up},
+ {'cmd': SQL__get_pg_temp_table_structure}
+ ]
+ rows, idx = run_rw_queries(link_obj = conn, queries = queries, return_data = True)
+ conn.rollback()
+ conn.close()
+ print(rows[0][0])
+
+ #--------------------------------------------------------------------
+ def test___get_schema_structure():
+ request_login_params(setup_pool = True)
+ with open('x-gm_func.txt', 'w', encoding = 'utf8') as f:
+ f.write(__get_schema_structure_by_gm_func())
+ with open('x-pg_temp_func.txt', 'w', encoding = 'utf8') as f:
+ f.write(__get_schema_structure_by_pg_temp_func())
+
#--------------------------------------------------------------------
# run tests
@@ -2749,7 +2866,7 @@ SELECT to_timestamp (foofoo,'YYMMDD.HH24MI') FROM (
#test_sanitize_pg_regex()
#test_is_pg_interval()
#test_sanity_check_time_skew()
- test_sanity_check_database_settings()
+ #test_sanity_check_database_settings()
#test_get_foreign_key_details()
#test_get_index_name()
#test_set_user_language()
@@ -2761,5 +2878,9 @@ SELECT to_timestamp (foofoo,'YYMMDD.HH24MI') FROM (
#test_faulty_SQL()
#test_log_settings()
#test_get_db_fingerprint()
+ #test_schema_compatible()
+ #test_get_schema_structure()
+ test___get_schema_structure()
+ #test_pg_temp_concat()
# ======================================================================
=====================================
server/sql/v21-v22/fixups/v22-gm-concat_table_structure_v19_and_up-fixup.sql
=====================================
@@ -11,6 +11,31 @@
--set default_transaction_read_only to off;
set check_function_bodies to on;
+-- --------------------------------------------------------------
+-- a few missing grants on (mostly unused) tables prevented
+-- accounts other than the owner (gm-dbo) from seeing them
+-- inside information_schema.tables which then throws off
+-- getting the database schema structure
+--
+-- now, this won't matter as long as gm.concat_table_structure()
+-- is used since that is owned by gm-dob _and_ also "security definer"
+--
+-- however, when using an ad-hoc temporary version in pg_temp to
+-- overcome other problems (such as missing CASTs) that version is
+-- owned and run by other accounts, which in turn won't see some
+-- rows in information_schema, making the function return a different
+-- table structure than is expected (and in the database)
+grant select, insert, update, delete on
+ clin.incoming_data_unmatchable,
+ clin.lnk_substance2episode,
+ ref.atc_staging -- no PK hence no PK sequence
+to group "gm-doctors";
+
+grant usage, select, update on
+ clin.incoming_data_unmatchable_pk_seq,
+ clin.lnk_substance2episode_pk_seq
+to group "gm-doctors";
+
-- --------------------------------------------------------------
create or replace function gm.concat_table_structure_v19_and_up()
returns text
@@ -122,6 +147,9 @@ begin
end;
';
+ALTER function gm.concat_table_structure_v19_and_up()
+ owner to "gm-dbo";
+
comment on function gm.concat_table_structure_v19_and_up() is
'new concat_table_structure() starting with gnumed_v19,
works on dem, clin, blobs, cfg, ref, i18n, bill,
@@ -129,4 +157,4 @@ comment on function gm.concat_table_structure_v19_and_up() is
sorts properly by bytea';
-- ==============================================================
-select gm.log_script_insertion('v22-gm-concat_table_structure_v19_and_up-fixup.sql', '22.18');
+select gm.log_script_insertion('v22-gm-concat_table_structure_v19_and_up-fixup.sql', '22.28');
=====================================
server/sql/v21-v22/fixups/v22-release_notes-fixup.sql
=====================================
@@ -17,24 +17,21 @@ INSERT INTO dem.message_inbox (
) VALUES (
(select pk from dem.staff where db_user = 'any-doc'),
(select pk_type from dem.v_inbox_item_type where type = 'memo' and category = 'administrative'),
- 'Release Notes for GNUmed 1.8.17 (database v22.27)',
- 'GNUmed 1.8.17 Release Notes:
+ 'Release Notes for GNUmed 1.8.18 (database v22.28)',
+ 'GNUmed 1.8.18 Release Notes:
- 1.8.17
+ 1.8.18
-FIX: patient search exception
-FIX: OOo startup exception
-FIX: placeholders today/date_of_birth/name parsing if no format given
-FIX: logging of invalid form templates
-FIX: logging of invalid address data
+IMPROVED: new-patient: dialog layout
+IMPROVED: phrasewheels: in-focus signalling
+IMPROVED: less diagnostic GTK output on console
-IMPROVED: EMR browser: link document review dlg from document nodes
-IMPROVED: configuration: logging of set-option failures
+ 22.28
- 22.27
+FIX: concatenation of the database schema structure
-NEW: add systemd .timer/.service files for scheduling database backup
+IMPROVED: documentation for backup systemd .service file
');
-- --------------------------------------------------------------
-select gm.log_script_insertion('v22-release_notes-fixup.sql', '22.27 at 1.8.17');
+select gm.log_script_insertion('v22-release_notes-fixup.sql', '22.28 at 1.8.18');
View it on GitLab: https://salsa.debian.org/med-team/gnumed-server/-/commit/9a9ffb0fd78b03d58b4484c5ff7771ada6cf8bb2
--
View it on GitLab: https://salsa.debian.org/med-team/gnumed-server/-/commit/9a9ffb0fd78b03d58b4484c5ff7771ada6cf8bb2
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20240128/5ac16f7e/attachment-0001.htm>
More information about the debian-med-commit
mailing list